Removed version number from file header.
[kai/samba.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 #include "nterr.h"
24 #include "sids.h"
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, 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, 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 /*****************************************************************************
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 *****************************************************************************/ 
203
204 BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
205                      uint32 acc_desired, uint32 *acc_granted, 
206                      NTSTATUS *status)
207 {
208         extern NT_USER_TOKEN anonymous_token;
209         size_t i;
210         SEC_ACL *the_acl;
211         fstring sid_str;
212         uint32 tmp_acc_desired = acc_desired;
213
214         if (!status || !acc_granted)
215                 return False;
216
217         if (!token)
218                 token = &anonymous_token;
219
220         *status = NT_STATUS_OK;
221         *acc_granted = 0;
222
223         DEBUG(10,("se_access_check: requested access 0x%08x, for NT token with %u entries and first sid %s.\n",
224                  (unsigned int)acc_desired, (unsigned int)token->num_sids,
225                 sid_to_string(sid_str, &token->user_sids[0])));
226
227         /*
228          * No security descriptor or security descriptor with no DACL
229          * present allows all access.
230          */
231
232         /* ACL must have something in it */
233
234         if (!sd || (sd && (!(sd->type & SEC_DESC_DACL_PRESENT) || sd->dacl == NULL))) {
235                 *status = NT_STATUS_OK;
236                 *acc_granted = acc_desired;
237                 DEBUG(5, ("se_access_check: no sd or blank DACL, access allowed\n"));
238                 return True;
239         }
240
241         /* The user sid is the first in the token */
242
243         DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
244
245         for (i = 1; i < token->num_sids; i++) {
246                 DEBUG(3, ("se_access_check: also %s\n",
247                           sid_to_string(sid_str, &token->user_sids[i])));
248         }
249
250         /* Is the token the owner of the SID ? */
251
252         if (sd->owner_sid) {
253                 for (i = 0; i < token->num_sids; i++) {
254                         if (sid_equal(&token->user_sids[i], sd->owner_sid)) {
255                                 /*
256                                  * The owner always has SEC_RIGHTS_WRITE_DAC & READ_CONTROL.
257                                  */
258                                 if (tmp_acc_desired & WRITE_DAC_ACCESS)
259                                         tmp_acc_desired &= ~WRITE_DAC_ACCESS;
260                                 if (tmp_acc_desired & READ_CONTROL_ACCESS)
261                                         tmp_acc_desired &= ~READ_CONTROL_ACCESS;
262                         }
263                 }
264         }
265
266         the_acl = sd->dacl;
267
268         if (tmp_acc_desired & MAXIMUM_ALLOWED_ACCESS) {
269                 tmp_acc_desired &= ~MAXIMUM_ALLOWED_ACCESS;
270                 return get_max_access( the_acl, token, acc_granted, tmp_acc_desired, 
271                                        status);
272         }
273
274         for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
275                 SEC_ACE *ace = &the_acl->ace[i];
276
277                 DEBUG(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
278                           (unsigned int)i, ace->type, ace->flags,
279                           sid_to_string(sid_str, &ace->trustee),
280                           (unsigned int) ace->info.mask, 
281                           (unsigned int)tmp_acc_desired ));
282
283                 tmp_acc_desired = check_ace( ace, token, tmp_acc_desired, status);
284                 if (NT_STATUS_V(*status)) {
285                         *acc_granted = 0;
286                         DEBUG(5,("se_access_check: ACE %u denied with status %s.\n", (unsigned int)i, get_nt_error_msg(*status)));
287                         return False;
288                 }
289         }
290
291         /*
292          * If there are no more desired permissions left then
293          * access was allowed.
294          */
295
296         if (tmp_acc_desired == 0) {
297                 *acc_granted = acc_desired;
298                 *status = NT_STATUS_OK;
299                 DEBUG(5,("se_access_check: access (%x) granted.\n", (unsigned int)acc_desired ));
300                 return True;
301         }
302                 
303         *acc_granted = 0;
304         *status = NT_STATUS_ACCESS_DENIED;
305         DEBUG(5,("se_access_check: access (%x) denied.\n", (unsigned int)acc_desired ));
306         return False;
307 }
308
309 /* Create a child security descriptor using another security descriptor as
310    the parent container.  This child object can either be a container or
311    non-container object. */
312
313 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
314                                       BOOL child_container)
315 {
316         SEC_DESC_BUF *sdb;
317         SEC_DESC *sd;
318         SEC_ACL *new_dacl, *the_acl;
319         SEC_ACE *new_ace_list = NULL;
320         int new_ace_list_ndx = 0, i;
321         size_t size;
322
323         /* Currently we only process the dacl when creating the child.  The
324            sacl should also be processed but this is left out as sacls are
325            not implemented in Samba at the moment.*/
326
327         the_acl = parent_ctr->dacl;
328
329         if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) 
330                 return NULL;
331
332         for (i = 0; the_acl && i < the_acl->num_aces; i++) {
333                 SEC_ACE *ace = &the_acl->ace[i];
334                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
335                 uint8 new_flags = 0;
336                 BOOL inherit = False;
337                 fstring sid_str;
338
339                 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
340                    inherited by non-container children objects.  Container
341                    children objects will inherit it as an INHERIT_ONLY
342                    ACE. */
343
344                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
345
346                         if (!child_container) {
347                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
348                         } else {
349                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
350                         }
351
352                         inherit = True;
353                 }
354
355                 /* The CONAINER_INHERIT_ACE flag means all child container
356                    objects will inherit and use the ACE. */
357
358                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
359                         if (!child_container) {
360                                 inherit = False;
361                         } else {
362                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
363                         }
364                 }
365
366                 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
367                    function for the parent container, but is inherited by
368                    all child objects as a normal ACE. */
369
370                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
371                         /* Move along, nothing to see here */
372                 }
373
374                 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
375                    is inherited by child objects but not grandchildren
376                    objects.  We clear the object inherit and container
377                    inherit flags in the inherited ACE. */
378
379                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
380                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
381                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
382                 }
383
384                 /* Add ACE to ACE list */
385
386                 if (!inherit)
387                         continue;
388
389                 init_sec_access(&new_ace->info, ace->info.mask);
390                 init_sec_ace(new_ace, &ace->trustee, ace->type,
391                              new_ace->info, new_flags);
392
393                 sid_to_string(sid_str, &ace->trustee);
394
395                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
396                           " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
397                           ace->type, ace->flags, ace->info.mask,
398                           sid_str, new_ace->type, new_ace->flags,
399                           new_ace->info.mask));
400
401                 new_ace_list_ndx++;
402         }
403
404         /* Create child security descriptor to return */
405         
406         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
407
408         /* Use the existing user and group sids.  I don't think this is
409            correct.  Perhaps the user and group should be passed in as
410            parameters by the caller? */
411
412         sd = make_sec_desc(ctx, SEC_DESC_REVISION,
413                            parent_ctr->owner_sid,
414                            parent_ctr->grp_sid,
415                            parent_ctr->sacl,
416                            new_dacl, &size);
417
418         sdb = make_sec_desc_buf(ctx, size, sd);
419
420         return sdb;
421 }