r23801: The FSF has moved around a lot. This fixes their Mass Ave address.
[samba.git] / source3 / lib / secdesc.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  SEC_DESC handling functions
4  *  Copyright (C) Andrew Tridgell              1992-1998,
5  *  Copyright (C) Jeremy R. Allison            1995-2003.
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7  *  Copyright (C) Paul Ashton                  1997-1998.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 3 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "includes.h"
24
25 /* Map generic permissions to file object specific permissions */
26
27 struct generic_mapping file_generic_mapping = {
28         FILE_GENERIC_READ,
29         FILE_GENERIC_WRITE,
30         FILE_GENERIC_EXECUTE,
31         FILE_GENERIC_ALL
32 };
33
34 /*******************************************************************
35  Works out the linearization size of a SEC_DESC.
36 ********************************************************************/
37
38 size_t sec_desc_size(SEC_DESC *psd)
39 {
40         size_t offset;
41
42         if (!psd) return 0;
43
44         offset = SEC_DESC_HEADER_SIZE;
45
46         /* don't align */
47
48         if (psd->owner_sid != NULL)
49                 offset += sid_size(psd->owner_sid);
50
51         if (psd->group_sid != NULL)
52                 offset += sid_size(psd->group_sid);
53
54         if (psd->sacl != NULL)
55                 offset += psd->sacl->size;
56
57         if (psd->dacl != NULL)
58                 offset += psd->dacl->size;
59
60         return offset;
61 }
62
63 /*******************************************************************
64  Compares two SEC_DESC structures
65 ********************************************************************/
66
67 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
68 {
69         /* Trivial case */
70
71         if (!s1 && !s2) {
72                 goto done;
73         }
74
75         if (!s1 || !s2) {
76                 return False;
77         }
78
79         /* Check top level stuff */
80
81         if (s1->revision != s2->revision) {
82                 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
83                            s1->revision, s2->revision));
84                 return False;
85         }
86
87         if (s1->type!= s2->type) {
88                 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
89                            s1->type, s2->type));
90                 return False;
91         }
92
93         /* Check owner and group */
94
95         if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
96                 fstring str1, str2;
97
98                 sid_to_string(str1, s1->owner_sid);
99                 sid_to_string(str2, s2->owner_sid);
100
101                 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
102                            str1, str2));
103                 return False;
104         }
105
106         if (!sid_equal(s1->group_sid, s2->group_sid)) {
107                 fstring str1, str2;
108
109                 sid_to_string(str1, s1->group_sid);
110                 sid_to_string(str2, s2->group_sid);
111
112                 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
113                            str1, str2));
114                 return False;
115         }
116
117         /* Check ACLs present in one but not the other */
118
119         if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
120             (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
121                 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
122                 return False;
123         }
124
125         /* Sigh - we have to do it the hard way by iterating over all
126            the ACEs in the ACLs */
127
128         if (!sec_acl_equal(s1->dacl, s2->dacl) ||
129             !sec_acl_equal(s1->sacl, s2->sacl)) {
130                 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
131                 return False;
132         }
133
134  done:
135         DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
136         return True;
137 }
138
139 /*******************************************************************
140  Merge part of security descriptor old_sec in to the empty sections of 
141  security descriptor new_sec.
142 ********************************************************************/
143
144 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
145 {
146         DOM_SID *owner_sid, *group_sid;
147         SEC_DESC_BUF *return_sdb;
148         SEC_ACL *dacl, *sacl;
149         SEC_DESC *psd = NULL;
150         uint16 secdesc_type;
151         size_t secdesc_size;
152
153         /* Copy over owner and group sids.  There seems to be no flag for
154            this so just check the pointer values. */
155
156         owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
157                 old_sdb->sd->owner_sid;
158
159         group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
160                 old_sdb->sd->group_sid;
161         
162         secdesc_type = new_sdb->sd->type;
163
164         /* Ignore changes to the system ACL.  This has the effect of making
165            changes through the security tab audit button not sticking. 
166            Perhaps in future Samba could implement these settings somehow. */
167
168         sacl = NULL;
169         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
170
171         /* Copy across discretionary ACL */
172
173         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
174                 dacl = new_sdb->sd->dacl;
175         } else {
176                 dacl = old_sdb->sd->dacl;
177         }
178
179         /* Create new security descriptor from bits */
180
181         psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
182                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
183
184         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
185
186         return(return_sdb);
187 }
188
189 /*******************************************************************
190  Creates a SEC_DESC structure
191 ********************************************************************/
192
193 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
194                         const DOM_SID *owner_sid, const DOM_SID *grp_sid,
195                         SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
196 {
197         SEC_DESC *dst;
198         uint32 offset     = 0;
199
200         *sd_size = 0;
201
202         if(( dst = TALLOC_ZERO_P(ctx, SEC_DESC)) == NULL)
203                 return NULL;
204
205         dst->revision = revision;
206         dst->type = type;
207
208         if (sacl)
209                 dst->type |= SEC_DESC_SACL_PRESENT;
210         if (dacl)
211                 dst->type |= SEC_DESC_DACL_PRESENT;
212
213         dst->owner_sid = NULL;
214         dst->group_sid   = NULL;
215         dst->sacl      = NULL;
216         dst->dacl      = NULL;
217
218         if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
219                 goto error_exit;
220
221         if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
222                 goto error_exit;
223
224         if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
225                 goto error_exit;
226
227         if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
228                 goto error_exit;
229
230         offset = SEC_DESC_HEADER_SIZE;
231
232         /*
233          * Work out the linearization sizes.
234          */
235
236         if (dst->sacl != NULL) {
237                 offset += dst->sacl->size;
238         }
239         if (dst->dacl != NULL) {
240                 offset += dst->dacl->size;
241         }
242
243         if (dst->owner_sid != NULL) {
244                 offset += sid_size(dst->owner_sid);
245         }
246
247         if (dst->group_sid != NULL) {
248                 offset += sid_size(dst->group_sid);
249         }
250
251         *sd_size = (size_t)offset;
252         return dst;
253
254 error_exit:
255
256         *sd_size = 0;
257         return NULL;
258 }
259
260 /*******************************************************************
261  Duplicate a SEC_DESC structure.  
262 ********************************************************************/
263
264 SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
265 {
266         size_t dummy;
267
268         if(src == NULL)
269                 return NULL;
270
271         return make_sec_desc( ctx, src->revision, src->type,
272                                 src->owner_sid, src->group_sid, src->sacl,
273                                 src->dacl, &dummy);
274 }
275
276 /*******************************************************************
277  Convert a secdesc into a byte stream
278 ********************************************************************/
279 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
280                            struct security_descriptor *secdesc,
281                            uint8 **data, size_t *len)
282 {
283         prs_struct ps;
284         
285         if (!prs_init(&ps, sec_desc_size(secdesc), mem_ctx, MARSHALL)) {
286                 return NT_STATUS_NO_MEMORY;
287         }
288
289         if (!sec_io_desc("security_descriptor", &secdesc, &ps, 1)) {
290                 prs_mem_free(&ps);
291                 return NT_STATUS_INVALID_PARAMETER;
292         }
293
294         if (!(*data = (uint8 *)talloc_memdup(mem_ctx, ps.data_p,
295                                              prs_offset(&ps)))) {
296                 prs_mem_free(&ps);
297                 return NT_STATUS_NO_MEMORY;
298         }
299
300         *len = prs_offset(&ps);
301         prs_mem_free(&ps);
302         return NT_STATUS_OK;
303 }
304
305 /*******************************************************************
306  Parse a byte stream into a secdesc
307 ********************************************************************/
308 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
309                              struct security_descriptor **psecdesc)
310 {
311         prs_struct ps;
312         struct security_descriptor *secdesc = NULL;
313
314         if (!(secdesc = TALLOC_ZERO_P(mem_ctx, struct security_descriptor))) {
315                 return NT_STATUS_NO_MEMORY;
316         }
317
318         if (!prs_init(&ps, 0, secdesc, UNMARSHALL)) {
319                 return NT_STATUS_NO_MEMORY;
320         }
321
322         prs_give_memory(&ps, (char *)data, len, False);
323
324         if (!sec_io_desc("security_descriptor", &secdesc, &ps, 1)) {
325                 return NT_STATUS_INVALID_PARAMETER;
326         }
327
328         prs_mem_free(&ps);
329         *psecdesc = secdesc;
330         return NT_STATUS_OK;
331 }
332
333 /*******************************************************************
334  Creates a SEC_DESC structure with typical defaults.
335 ********************************************************************/
336
337 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid,
338                                  SEC_ACL *dacl, size_t *sd_size)
339 {
340         return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
341                              owner_sid, grp_sid, NULL, dacl, sd_size);
342 }
343
344 /*******************************************************************
345  Creates a SEC_DESC_BUF structure.
346 ********************************************************************/
347
348 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
349 {
350         SEC_DESC_BUF *dst;
351
352         if((dst = TALLOC_ZERO_P(ctx, SEC_DESC_BUF)) == NULL)
353                 return NULL;
354
355         /* max buffer size (allocated size) */
356         dst->sd_size = (uint32)len;
357         
358         if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
359                 return NULL;
360         }
361
362         return dst;
363 }
364
365 /*******************************************************************
366  Duplicates a SEC_DESC_BUF structure.
367 ********************************************************************/
368
369 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
370 {
371         if(src == NULL)
372                 return NULL;
373
374         return make_sec_desc_buf( ctx, src->sd_size, src->sd);
375 }
376
377 /*******************************************************************
378  Add a new SID with its permissions to SEC_DESC.
379 ********************************************************************/
380
381 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
382 {
383         SEC_DESC *sd   = 0;
384         SEC_ACL  *dacl = 0;
385         SEC_ACE  *ace  = 0;
386         NTSTATUS  status;
387
388         if (!ctx || !psd || !sid || !sd_size)
389                 return NT_STATUS_INVALID_PARAMETER;
390
391         *sd_size = 0;
392
393         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
394         
395         if (!NT_STATUS_IS_OK(status))
396                 return status;
397
398         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
399                 return NT_STATUS_UNSUCCESSFUL;
400         
401         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
402                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
403                 return NT_STATUS_UNSUCCESSFUL;
404
405         *psd = sd;
406          sd  = 0;
407         return NT_STATUS_OK;
408 }
409
410 /*******************************************************************
411  Modify a SID's permissions in a SEC_DESC.
412 ********************************************************************/
413
414 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
415 {
416         NTSTATUS status;
417
418         if (!sd || !sid)
419                 return NT_STATUS_INVALID_PARAMETER;
420
421         status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
422
423         if (!NT_STATUS_IS_OK(status))
424                 return status;
425         
426         return NT_STATUS_OK;
427 }
428
429 /*******************************************************************
430  Delete a SID from a SEC_DESC.
431 ********************************************************************/
432
433 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
434 {
435         SEC_DESC *sd   = 0;
436         SEC_ACL  *dacl = 0;
437         SEC_ACE  *ace  = 0;
438         NTSTATUS  status;
439
440         if (!ctx || !psd[0] || !sid || !sd_size)
441                 return NT_STATUS_INVALID_PARAMETER;
442
443         *sd_size = 0;
444         
445         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
446
447         if (!NT_STATUS_IS_OK(status))
448                 return status;
449
450         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
451                 return NT_STATUS_UNSUCCESSFUL;
452         
453         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
454                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
455                 return NT_STATUS_UNSUCCESSFUL;
456
457         *psd = sd;
458          sd  = 0;
459         return NT_STATUS_OK;
460 }
461
462 /* Create a child security descriptor using another security descriptor as
463    the parent container.  This child object can either be a container or
464    non-container object. */
465
466 SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, 
467                                       BOOL child_container)
468 {
469         SEC_DESC_BUF *sdb;
470         SEC_DESC *sd;
471         SEC_ACL *new_dacl, *the_acl;
472         SEC_ACE *new_ace_list = NULL;
473         unsigned int new_ace_list_ndx = 0, i;
474         size_t size;
475
476         /* Currently we only process the dacl when creating the child.  The
477            sacl should also be processed but this is left out as sacls are
478            not implemented in Samba at the moment.*/
479
480         the_acl = parent_ctr->dacl;
481
482         if (the_acl->num_aces) {
483                 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE, the_acl->num_aces))) 
484                         return NULL;
485         } else {
486                 new_ace_list = NULL;
487         }
488
489         for (i = 0; i < the_acl->num_aces; i++) {
490                 SEC_ACE *ace = &the_acl->aces[i];
491                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
492                 uint8 new_flags = 0;
493                 BOOL inherit = False;
494                 fstring sid_str;
495
496                 /* The OBJECT_INHERIT_ACE flag causes the ACE to be
497                    inherited by non-container children objects.  Container
498                    children objects will inherit it as an INHERIT_ONLY
499                    ACE. */
500
501                 if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) {
502
503                         if (!child_container) {
504                                 new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT;
505                         } else {
506                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
507                         }
508
509                         inherit = True;
510                 }
511
512                 /* The CONAINER_INHERIT_ACE flag means all child container
513                    objects will inherit and use the ACE. */
514
515                 if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
516                         if (!child_container) {
517                                 inherit = False;
518                         } else {
519                                 new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT;
520                         }
521                 }
522
523                 /* The INHERIT_ONLY_ACE is not used by the se_access_check()
524                    function for the parent container, but is inherited by
525                    all child objects as a normal ACE. */
526
527                 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
528                         /* Move along, nothing to see here */
529                 }
530
531                 /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE
532                    is inherited by child objects but not grandchildren
533                    objects.  We clear the object inherit and container
534                    inherit flags in the inherited ACE. */
535
536                 if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
537                         new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT |
538                                        SEC_ACE_FLAG_CONTAINER_INHERIT);
539                 }
540
541                 /* Add ACE to ACE list */
542
543                 if (!inherit)
544                         continue;
545
546                 init_sec_access(&new_ace->access_mask, ace->access_mask);
547                 init_sec_ace(new_ace, &ace->trustee, ace->type,
548                              new_ace->access_mask, new_flags);
549
550                 sid_to_string(sid_str, &ace->trustee);
551
552                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
553                           " inherited as %s:%d/0x%02x/0x%08x\n", sid_str,
554                           ace->type, ace->flags, ace->access_mask,
555                           sid_str, new_ace->type, new_ace->flags,
556                           new_ace->access_mask));
557
558                 new_ace_list_ndx++;
559         }
560
561         /* Create child security descriptor to return */
562         
563         new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list);
564
565         /* Use the existing user and group sids.  I don't think this is
566            correct.  Perhaps the user and group should be passed in as
567            parameters by the caller? */
568
569         sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
570                            parent_ctr->owner_sid,
571                            parent_ctr->group_sid,
572                            parent_ctr->sacl,
573                            new_dacl, &size);
574
575         sdb = make_sec_desc_buf(ctx, size, sd);
576
577         return sdb;
578 }
579
580 /*******************************************************************
581  Sets up a SEC_ACCESS structure.
582 ********************************************************************/
583
584 void init_sec_access(uint32 *t, uint32 mask)
585 {
586         *t = mask;
587 }
588
589