~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/secdesc.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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