Send back talloc allocation information when POOL_USAGE is received.
[samba.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 /**********************************************************************************
28  Check if this ACE has a SID in common with the token.
29 **********************************************************************************/
30
31 static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
32 {
33         size_t i;
34
35         for (i = 0; i < token->num_sids; i++) {
36                 if (sid_equal(&ace->trustee, &token->user_sids[i]))
37                         return True;
38         }
39
40         return False;
41 }
42
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 **********************************************************************************/
47
48 static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired, 
49                         NTSTATUS *status)
50 {
51         uint32 mask = ace->info.mask;
52
53         /*
54          * Inherit only is ignored.
55          */
56
57         if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
58                 return acc_desired;
59         }
60
61         /*
62          * If this ACE has no SID in common with the token,
63          * ignore it as it cannot be used to make an access
64          * determination.
65          */
66
67         if (!token_sid_in_ace( token, ace))
68                 return acc_desired;     
69
70         switch (ace->type) {
71                 case SEC_ACE_TYPE_ACCESS_ALLOWED:
72                         /*
73                          * This is explicitly allowed.
74                          * Remove the bits from the remaining
75                          * access required. Return the remaining
76                          * bits needed.
77                          */
78                         acc_desired &= ~mask;
79                         break;
80                 case SEC_ACE_TYPE_ACCESS_DENIED:
81                         /*
82                          * This is explicitly denied.
83                          * If any bits match terminate here,
84                          * we are denied.
85                          */
86                         if (acc_desired & mask) {
87                                 *status = NT_STATUS_ACCESS_DENIED;
88                                 return 0xFFFFFFFF;
89                         }
90                         break;
91                 case SEC_ACE_TYPE_SYSTEM_ALARM:
92                 case SEC_ACE_TYPE_SYSTEM_AUDIT:
93                         *status = NT_STATUS_NOT_IMPLEMENTED;
94                         return 0xFFFFFFFF;
95                 default:
96                         *status = NT_STATUS_INVALID_PARAMETER;
97                         return 0xFFFFFFFF;
98         }
99
100         return acc_desired;
101 }
102
103 /*********************************************************************************
104  Maximum access was requested. Calculate the max possible. Fail if it doesn't
105  include other bits requested.
106 **********************************************************************************/ 
107
108 static BOOL get_max_access( SEC_ACL *the_acl, NT_USER_TOKEN *token, uint32 *granted, 
109                             uint32 desired, 
110                             NTSTATUS *status)
111 {
112         uint32 acc_denied = 0;
113         uint32 acc_granted = 0;
114         size_t i;
115         
116         for ( i = 0 ; i < the_acl->num_aces; i++) {
117                 SEC_ACE *ace = &the_acl->ace[i];
118                 uint32 mask = ace->info.mask;
119
120                 if (!token_sid_in_ace( token, ace))
121                         continue;
122
123                 switch (ace->type) {
124                         case SEC_ACE_TYPE_ACCESS_ALLOWED:
125                                 acc_granted |= (mask & ~acc_denied);
126                                 break;
127                         case SEC_ACE_TYPE_ACCESS_DENIED:
128                                 acc_denied |= (mask & ~acc_granted);
129                                 break;
130                         case SEC_ACE_TYPE_SYSTEM_ALARM:
131                         case SEC_ACE_TYPE_SYSTEM_AUDIT:
132                                 *status = NT_STATUS_NOT_IMPLEMENTED;
133                                 *granted = 0;
134                                 return False;
135                         default:
136                                 *status = NT_STATUS_INVALID_PARAMETER;
137                                 *granted = 0;
138                                 return False;
139                 }                           
140         }
141
142         /*
143          * If we were granted no access, or we desired bits that we
144          * didn't get, then deny.
145          */
146
147         if ((acc_granted == 0) || ((acc_granted & desired) != desired)) {
148                 *status = NT_STATUS_ACCESS_DENIED;
149                 *granted = 0;
150                 return False;
151         }
152
153         /*
154          * Return the access we did get.
155          */
156
157         *granted = acc_granted;
158         *status = NT_STATUS_OK;
159         return True;
160 }
161
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. */
166
167 void se_map_generic(uint32 *access_mask, struct generic_mapping *mapping)
168 {
169         uint32 old_mask = *access_mask;
170
171         if (*access_mask & GENERIC_READ_ACCESS) {
172                 *access_mask &= ~GENERIC_READ_ACCESS;
173                 *access_mask |= mapping->generic_read;
174         }
175
176         if (*access_mask & GENERIC_WRITE_ACCESS) {
177                 *access_mask &= ~GENERIC_WRITE_ACCESS;
178                 *access_mask |= mapping->generic_write;
179         }
180
181         if (*access_mask & GENERIC_EXECUTE_ACCESS) {
182                 *access_mask &= ~GENERIC_EXECUTE_ACCESS;
183                 *access_mask |= mapping->generic_execute;
184         }
185
186         if (*access_mask & GENERIC_ALL_ACCESS) {
187                 *access_mask &= ~GENERIC_ALL_ACCESS;
188                 *access_mask |= mapping->generic_all;
189         }
190
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));
194         }
195 }
196
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 *****************************************************************************/ 
204
205 BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
206                      uint32 acc_desired, uint32 *acc_granted, 
207                      NTSTATUS *status)
208 {
209         extern NT_USER_TOKEN anonymous_token;
210         size_t i;
211         SEC_ACL *the_acl;
212         fstring sid_str;
213         uint32 tmp_acc_desired = acc_desired;
214
215         if (!status || !acc_granted)
216                 return False;
217
218         if (!token)
219                 token = &anonymous_token;
220
221         *status = NT_STATUS_OK;
222         *acc_granted = 0;
223
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])));
227
228         /*
229          * No security descriptor or security descriptor with no DACL
230          * present allows all access.
231          */
232
233         /* ACL must have something in it */
234
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"));
239                 return True;
240         }
241
242         /* The user sid is the first in the token */
243
244         DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
245
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])));
249         }
250
251         /* Is the token the owner of the SID ? */
252
253         if (sd->owner_sid) {
254                 for (i = 0; i < token->num_sids; i++) {
255                         if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
256                                 /*
257                                  * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
258                                  */
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;
263                         }
264                 }
265         }
266
267         the_acl = sd->dacl;
268
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, 
272                                        status);
273         }
274
275         for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
276                 SEC_ACE *ace = &the_acl->ace[i];
277
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 ));
283
284                 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
285                 if (NT_STATUS_V(*status)) {
286                         *acc_granted = 0;
287                         DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, get_nt_error_msg(*status)));
288                         return False;
289                 }
290         }
291
292         /*
293          * If there are no more desired permissions left then
294          * access was allowed.
295          */
296
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 ));
301                 return True;
302         }
303                 
304         *acc_granted = 0;
305         *status = NT_STATUS_ACCESS_DENIED;
306         DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
307         return False;
308 }
309
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. */
313
314 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
315                                       BOOL child_container)
316 {
317         SEC_DESC_BUF *sdb;
318         SEC_DESC *sd;
319         SEC_ACL *new_dacl, *the_acl;
320         SEC_ACE *new_ace_list = NULL;
321         int new_ace_list_ndx = 0, i;
322         size_t size;
323
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.*/
327
328         the_acl = parent_ctr->dacl;
329
330         if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) 
331                 return NULL;
332
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];
336                 uint8 new_flags = 0;
337                 BOOL inherit = False;
338                 fstring sid_str;
339
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
343                    ACE. */
344
345                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
346
347                         if (!child_container) {
348                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
349                         } else {
350                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
351                         }
352
353                         inherit = True;
354                 }
355
356                 /* The CONAINER_INHERIT_ACE flag means all child container
357                    objects will inherit and use the ACE. */
358
359                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
360                         if (!child_container) {
361                                 inherit = False;
362                         } else {
363                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
364                         }
365                 }
366
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. */
370
371                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
372                         /* Move along, nothing to see here */
373                 }
374
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. */
379
380                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
381                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
382                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
383                 }
384
385                 /* Add ACE to ACE list */
386
387                 if (!inherit)
388                         continue;
389
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);
393
394                 sid_to_string(sid_str, &ace->trustee);
395
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));
401
402                 new_ace_list_ndx++;
403         }
404
405         /* Create child security descriptor to return */
406         
407         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
408
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? */
412
413         sd = make_sec_desc(ctx, SEC_DESC_REVISION,
414                            parent_ctr->owner_sid,
415                            parent_ctr->grp_sid,
416                            parent_ctr->sacl,
417                            new_dacl, &size);
418
419         sdb = make_sec_desc_buf(ctx, size, sd);
420
421         return sdb;
422 }