s3-ldap: fix more callers of smbldap_dn_talloc() that were passing a NULL context.
[ira/wip.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 const 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  Given a security_descriptor return the sec_info.
36 ********************************************************************/
37
38 uint32_t get_sec_info(const SEC_DESC *sd)
39 {
40         uint32_t sec_info = ALL_SECURITY_INFORMATION;
41
42         SMB_ASSERT(sd);
43
44         if (sd->owner_sid == NULL) {
45                 sec_info &= ~OWNER_SECURITY_INFORMATION;
46         }
47         if (sd->group_sid == NULL) {
48                 sec_info &= ~GROUP_SECURITY_INFORMATION;
49         }
50         if (sd->sacl == NULL) {
51                 sec_info &= ~SACL_SECURITY_INFORMATION;
52         }
53         if (sd->dacl == NULL) {
54                 sec_info &= ~DACL_SECURITY_INFORMATION;
55         }
56
57         return sec_info;
58 }
59
60
61 /*******************************************************************
62  Merge part of security descriptor old_sec in to the empty sections of 
63  security descriptor new_sec.
64 ********************************************************************/
65
66 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
67 {
68         DOM_SID *owner_sid, *group_sid;
69         SEC_DESC_BUF *return_sdb;
70         SEC_ACL *dacl, *sacl;
71         SEC_DESC *psd = NULL;
72         uint16 secdesc_type;
73         size_t secdesc_size;
74
75         /* Copy over owner and group sids.  There seems to be no flag for
76            this so just check the pointer values. */
77
78         owner_sid = new_sdb->sd->owner_sid ? new_sdb->sd->owner_sid :
79                 old_sdb->sd->owner_sid;
80
81         group_sid = new_sdb->sd->group_sid ? new_sdb->sd->group_sid :
82                 old_sdb->sd->group_sid;
83         
84         secdesc_type = new_sdb->sd->type;
85
86         /* Ignore changes to the system ACL.  This has the effect of making
87            changes through the security tab audit button not sticking. 
88            Perhaps in future Samba could implement these settings somehow. */
89
90         sacl = NULL;
91         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
92
93         /* Copy across discretionary ACL */
94
95         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
96                 dacl = new_sdb->sd->dacl;
97         } else {
98                 dacl = old_sdb->sd->dacl;
99         }
100
101         /* Create new security descriptor from bits */
102
103         psd = make_sec_desc(ctx, new_sdb->sd->revision, secdesc_type,
104                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
105
106         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
107
108         return(return_sdb);
109 }
110
111 /*******************************************************************
112  Creates a SEC_DESC structure
113 ********************************************************************/
114
115 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx,
116                         enum security_descriptor_revision revision,
117                         uint16 type,
118                         const DOM_SID *owner_sid, const DOM_SID *grp_sid,
119                         SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
120 {
121         SEC_DESC *dst;
122         uint32 offset     = 0;
123
124         *sd_size = 0;
125
126         if(( dst = TALLOC_ZERO_P(ctx, SEC_DESC)) == NULL)
127                 return NULL;
128
129         dst->revision = revision;
130         dst->type = type;
131
132         if (sacl)
133                 dst->type |= SEC_DESC_SACL_PRESENT;
134         if (dacl)
135                 dst->type |= SEC_DESC_DACL_PRESENT;
136
137         dst->owner_sid = NULL;
138         dst->group_sid   = NULL;
139         dst->sacl      = NULL;
140         dst->dacl      = NULL;
141
142         if(owner_sid && ((dst->owner_sid = sid_dup_talloc(dst,owner_sid)) == NULL))
143                 goto error_exit;
144
145         if(grp_sid && ((dst->group_sid = sid_dup_talloc(dst,grp_sid)) == NULL))
146                 goto error_exit;
147
148         if(sacl && ((dst->sacl = dup_sec_acl(dst, sacl)) == NULL))
149                 goto error_exit;
150
151         if(dacl && ((dst->dacl = dup_sec_acl(dst, dacl)) == NULL))
152                 goto error_exit;
153
154         offset = SEC_DESC_HEADER_SIZE;
155
156         /*
157          * Work out the linearization sizes.
158          */
159
160         if (dst->sacl != NULL) {
161                 offset += dst->sacl->size;
162         }
163         if (dst->dacl != NULL) {
164                 offset += dst->dacl->size;
165         }
166
167         if (dst->owner_sid != NULL) {
168                 offset += ndr_size_dom_sid(dst->owner_sid, NULL, 0);
169         }
170
171         if (dst->group_sid != NULL) {
172                 offset += ndr_size_dom_sid(dst->group_sid, NULL, 0);
173         }
174
175         *sd_size = (size_t)offset;
176         return dst;
177
178 error_exit:
179
180         *sd_size = 0;
181         return NULL;
182 }
183
184 /*******************************************************************
185  Duplicate a SEC_DESC structure.  
186 ********************************************************************/
187
188 SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src)
189 {
190         size_t dummy;
191
192         if(src == NULL)
193                 return NULL;
194
195         return make_sec_desc( ctx, src->revision, src->type,
196                                 src->owner_sid, src->group_sid, src->sacl,
197                                 src->dacl, &dummy);
198 }
199
200 /*******************************************************************
201  Convert a secdesc into a byte stream
202 ********************************************************************/
203 NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx,
204                            struct security_descriptor *secdesc,
205                            uint8 **data, size_t *len)
206 {
207         DATA_BLOB blob;
208         enum ndr_err_code ndr_err;
209
210         ndr_err = ndr_push_struct_blob(
211                 &blob, mem_ctx, NULL, secdesc,
212                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
213
214         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
215                 DEBUG(0, ("ndr_push_security_descriptor failed: %s\n",
216                           ndr_errstr(ndr_err)));
217                 return ndr_map_error2ntstatus(ndr_err);;
218         }
219
220         *data = blob.data;
221         *len = blob.length;
222         return NT_STATUS_OK;
223 }
224
225 /*******************************************************************
226  Convert a secdesc_buf into a byte stream
227 ********************************************************************/
228
229 NTSTATUS marshall_sec_desc_buf(TALLOC_CTX *mem_ctx,
230                                struct sec_desc_buf *secdesc_buf,
231                                uint8_t **data, size_t *len)
232 {
233         DATA_BLOB blob;
234         enum ndr_err_code ndr_err;
235
236         ndr_err = ndr_push_struct_blob(
237                 &blob, mem_ctx, NULL, secdesc_buf,
238                 (ndr_push_flags_fn_t)ndr_push_sec_desc_buf);
239
240         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
241                 DEBUG(0, ("ndr_push_sec_desc_buf failed: %s\n",
242                           ndr_errstr(ndr_err)));
243                 return ndr_map_error2ntstatus(ndr_err);;
244         }
245
246         *data = blob.data;
247         *len = blob.length;
248         return NT_STATUS_OK;
249 }
250
251 /*******************************************************************
252  Parse a byte stream into a secdesc
253 ********************************************************************/
254 NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len,
255                              struct security_descriptor **psecdesc)
256 {
257         DATA_BLOB blob;
258         enum ndr_err_code ndr_err;
259         struct security_descriptor *result;
260
261         if ((data == NULL) || (len == 0)) {
262                 return NT_STATUS_INVALID_PARAMETER;
263         }
264
265         result = TALLOC_ZERO_P(mem_ctx, struct security_descriptor);
266         if (result == NULL) {
267                 return NT_STATUS_NO_MEMORY;
268         }
269
270         blob = data_blob_const(data, len);
271
272         ndr_err = ndr_pull_struct_blob(
273                 &blob, result, NULL, result,
274                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
275
276         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
277                 DEBUG(0, ("ndr_pull_security_descriptor failed: %s\n",
278                           ndr_errstr(ndr_err)));
279                 TALLOC_FREE(result);
280                 return ndr_map_error2ntstatus(ndr_err);;
281         }
282
283         *psecdesc = result;
284         return NT_STATUS_OK;
285 }
286
287 /*******************************************************************
288  Parse a byte stream into a sec_desc_buf
289 ********************************************************************/
290
291 NTSTATUS unmarshall_sec_desc_buf(TALLOC_CTX *mem_ctx, uint8_t *data, size_t len,
292                                  struct sec_desc_buf **psecdesc_buf)
293 {
294         DATA_BLOB blob;
295         enum ndr_err_code ndr_err;
296         struct sec_desc_buf *result;
297
298         if ((data == NULL) || (len == 0)) {
299                 return NT_STATUS_INVALID_PARAMETER;
300         }
301
302         result = TALLOC_ZERO_P(mem_ctx, struct sec_desc_buf);
303         if (result == NULL) {
304                 return NT_STATUS_NO_MEMORY;
305         }
306
307         blob = data_blob_const(data, len);
308
309         ndr_err = ndr_pull_struct_blob(
310                 &blob, result, NULL, result,
311                 (ndr_pull_flags_fn_t)ndr_pull_sec_desc_buf);
312
313         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
314                 DEBUG(0, ("ndr_pull_sec_desc_buf failed: %s\n",
315                           ndr_errstr(ndr_err)));
316                 TALLOC_FREE(result);
317                 return ndr_map_error2ntstatus(ndr_err);;
318         }
319
320         *psecdesc_buf = result;
321         return NT_STATUS_OK;
322 }
323
324 /*******************************************************************
325  Creates a SEC_DESC structure with typical defaults.
326 ********************************************************************/
327
328 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid,
329                                  SEC_ACL *dacl, size_t *sd_size)
330 {
331         return make_sec_desc(ctx, SECURITY_DESCRIPTOR_REVISION_1,
332                              SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL,
333                              dacl, sd_size);
334 }
335
336 /*******************************************************************
337  Creates a SEC_DESC_BUF structure.
338 ********************************************************************/
339
340 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
341 {
342         SEC_DESC_BUF *dst;
343
344         if((dst = TALLOC_ZERO_P(ctx, SEC_DESC_BUF)) == NULL)
345                 return NULL;
346
347         /* max buffer size (allocated size) */
348         dst->sd_size = (uint32)len;
349         
350         if(sec_desc && ((dst->sd = dup_sec_desc(ctx, sec_desc)) == NULL)) {
351                 return NULL;
352         }
353
354         return dst;
355 }
356
357 /*******************************************************************
358  Duplicates a SEC_DESC_BUF structure.
359 ********************************************************************/
360
361 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
362 {
363         if(src == NULL)
364                 return NULL;
365
366         return make_sec_desc_buf( ctx, src->sd_size, src->sd);
367 }
368
369 /*******************************************************************
370  Add a new SID with its permissions to SEC_DESC.
371 ********************************************************************/
372
373 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
374 {
375         SEC_DESC *sd   = 0;
376         SEC_ACL  *dacl = 0;
377         SEC_ACE  *ace  = 0;
378         NTSTATUS  status;
379
380         if (!ctx || !psd || !sid || !sd_size)
381                 return NT_STATUS_INVALID_PARAMETER;
382
383         *sd_size = 0;
384
385         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid, mask);
386         
387         if (!NT_STATUS_IS_OK(status))
388                 return status;
389
390         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
391                 return NT_STATUS_UNSUCCESSFUL;
392         
393         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
394                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
395                 return NT_STATUS_UNSUCCESSFUL;
396
397         *psd = sd;
398          sd  = 0;
399         return NT_STATUS_OK;
400 }
401
402 /*******************************************************************
403  Modify a SID's permissions in a SEC_DESC.
404 ********************************************************************/
405
406 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
407 {
408         NTSTATUS status;
409
410         if (!sd || !sid)
411                 return NT_STATUS_INVALID_PARAMETER;
412
413         status = sec_ace_mod_sid(sd->dacl->aces, sd->dacl->num_aces, sid, mask);
414
415         if (!NT_STATUS_IS_OK(status))
416                 return status;
417         
418         return NT_STATUS_OK;
419 }
420
421 /*******************************************************************
422  Delete a SID from a SEC_DESC.
423 ********************************************************************/
424
425 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
426 {
427         SEC_DESC *sd   = 0;
428         SEC_ACL  *dacl = 0;
429         SEC_ACE  *ace  = 0;
430         NTSTATUS  status;
431
432         if (!ctx || !psd[0] || !sid || !sd_size)
433                 return NT_STATUS_INVALID_PARAMETER;
434
435         *sd_size = 0;
436         
437         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->aces, &psd[0]->dacl->num_aces, sid);
438
439         if (!NT_STATUS_IS_OK(status))
440                 return status;
441
442         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
443                 return NT_STATUS_UNSUCCESSFUL;
444         
445         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
446                 psd[0]->group_sid, psd[0]->sacl, dacl, sd_size)))
447                 return NT_STATUS_UNSUCCESSFUL;
448
449         *psd = sd;
450          sd  = 0;
451         return NT_STATUS_OK;
452 }
453
454 /*
455  * Determine if an ACE is inheritable
456  */
457
458 static bool is_inheritable_ace(const SEC_ACE *ace,
459                                 bool container)
460 {
461         if (!container) {
462                 return ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) != 0);
463         }
464
465         if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) {
466                 return true;
467         }
468
469         if ((ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) &&
470                         !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
471                 return true;
472         }
473
474         return false;
475 }
476
477 /* Create a child security descriptor using another security descriptor as
478    the parent container.  This child object can either be a container or
479    non-container object. */
480
481 NTSTATUS se_create_child_secdesc(TALLOC_CTX *ctx,
482                                         SEC_DESC **ppsd,
483                                         size_t *psize,
484                                         const SEC_DESC *parent_ctr,
485                                         const DOM_SID *owner_sid,
486                                         const DOM_SID *group_sid,
487                                         bool container)
488 {
489         SEC_ACL *new_dacl = NULL, *the_acl = NULL;
490         SEC_ACE *new_ace_list = NULL;
491         unsigned int new_ace_list_ndx = 0, i;
492
493         *ppsd = NULL;
494         *psize = 0;
495
496         /* Currently we only process the dacl when creating the child.  The
497            sacl should also be processed but this is left out as sacls are
498            not implemented in Samba at the moment.*/
499
500         the_acl = parent_ctr->dacl;
501
502         if (the_acl->num_aces) {
503                 if (2*the_acl->num_aces < the_acl->num_aces) {
504                         return NT_STATUS_NO_MEMORY;
505                 }
506
507                 if (!(new_ace_list = TALLOC_ARRAY(ctx, SEC_ACE,
508                                                 2*the_acl->num_aces))) {
509                         return NT_STATUS_NO_MEMORY;
510                 }
511         } else {
512                 new_ace_list = NULL;
513         }
514
515         for (i = 0; i < the_acl->num_aces; i++) {
516                 const SEC_ACE *ace = &the_acl->aces[i];
517                 SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx];
518                 const DOM_SID *ptrustee = &ace->trustee;
519                 const DOM_SID *creator = NULL;
520                 uint8 new_flags = ace->flags;
521
522                 if (!is_inheritable_ace(ace, container)) {
523                         continue;
524                 }
525
526                 /* see the RAW-ACLS inheritance test for details on these rules */
527                 if (!container) {
528                         new_flags = 0;
529                 } else {
530                         new_flags &= ~SEC_ACE_FLAG_INHERIT_ONLY;
531
532                         if (!(new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
533                                 new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
534                         }
535                         if (new_flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) {
536                                 new_flags = 0;
537                         }
538                 }
539
540                 /* The CREATOR sids are special when inherited */
541                 if (sid_equal(ptrustee, &global_sid_Creator_Owner)) {
542                         creator = &global_sid_Creator_Owner;
543                         ptrustee = owner_sid;
544                 } else if (sid_equal(ptrustee, &global_sid_Creator_Group)) {
545                         creator = &global_sid_Creator_Group;
546                         ptrustee = group_sid;
547                 }
548
549                 if (creator && container &&
550                                 (new_flags & SEC_ACE_FLAG_CONTAINER_INHERIT)) {
551
552                         /* First add the regular ACE entry. */
553                         init_sec_ace(new_ace, ptrustee, ace->type,
554                                 ace->access_mask, 0);
555
556                         DEBUG(5,("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x"
557                                 " inherited as %s:%d/0x%02x/0x%08x\n",
558                                 sid_string_dbg(&ace->trustee),
559                                 ace->type, ace->flags, ace->access_mask,
560                                 sid_string_dbg(&new_ace->trustee),
561                                 new_ace->type, new_ace->flags,
562                                 new_ace->access_mask));
563
564                         new_ace_list_ndx++;
565
566                         /* Now add the extra creator ACE. */
567                         new_ace = &new_ace_list[new_ace_list_ndx];
568
569                         ptrustee = creator;
570                         new_flags |= SEC_ACE_FLAG_INHERIT_ONLY;
571                 } else if (container &&
572                                 !(ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT)) {
573                         ptrustee = &ace->trustee;
574                 }
575
576                 init_sec_ace(new_ace, ptrustee, ace->type,
577                              ace->access_mask, new_flags);
578
579                 DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x "
580                           " inherited as %s:%d/0x%02x/0x%08x\n",
581                           sid_string_dbg(&ace->trustee),
582                           ace->type, ace->flags, ace->access_mask,
583                           sid_string_dbg(&ace->trustee),
584                           new_ace->type, new_ace->flags,
585                           new_ace->access_mask));
586
587                 new_ace_list_ndx++;
588         }
589
590         /* Create child security descriptor to return */
591         if (new_ace_list_ndx) {
592                 new_dacl = make_sec_acl(ctx,
593                                 NT4_ACL_REVISION,
594                                 new_ace_list_ndx,
595                                 new_ace_list);
596
597                 if (!new_dacl) {
598                         return NT_STATUS_NO_MEMORY;
599                 }
600         }
601
602         *ppsd = make_sec_desc(ctx,
603                         SECURITY_DESCRIPTOR_REVISION_1,
604                         SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
605                         owner_sid,
606                         group_sid,
607                         NULL,
608                         new_dacl,
609                         psize);
610         if (!*ppsd) {
611                 return NT_STATUS_NO_MEMORY;
612         }
613         return NT_STATUS_OK;
614 }
615
616 NTSTATUS se_create_child_secdesc_buf(TALLOC_CTX *ctx,
617                                         SEC_DESC_BUF **ppsdb,
618                                         const SEC_DESC *parent_ctr,
619                                         bool container)
620 {
621         NTSTATUS status;
622         size_t size = 0;
623         SEC_DESC *sd = NULL;
624
625         *ppsdb = NULL;
626         status = se_create_child_secdesc(ctx,
627                                         &sd,
628                                         &size,
629                                         parent_ctr,
630                                         parent_ctr->owner_sid,
631                                         parent_ctr->group_sid,
632                                         container);
633         if (!NT_STATUS_IS_OK(status)) {
634                 return status;
635         }
636
637         *ppsdb = make_sec_desc_buf(ctx, size, sd);
638         if (!*ppsdb) {
639                 return NT_STATUS_NO_MEMORY;
640         }
641         return NT_STATUS_OK;
642 }