2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998,
5 * Copyright (C) Jeremy R. Allison 1995-1998
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7 * Copyright (C) Paul Ashton 1997-1998.
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 2 of the License, or
12 * (at your option) any later version.
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define SD_HEADER_SIZE 0x14
28 /*******************************************************************
29 Sets up a SEC_ACCESS structure.
30 ********************************************************************/
32 void init_sec_access(SEC_ACCESS *t, uint32 mask)
37 /*******************************************************************
38 Reads or writes a SEC_ACCESS structure.
39 ********************************************************************/
41 BOOL sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
46 prs_debug(ps, depth, desc, "sec_io_access");
52 if(!prs_uint32("mask", ps, depth, &(t->mask)))
59 /*******************************************************************
60 Sets up a SEC_ACE structure.
61 ********************************************************************/
63 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
67 t->size = sid_size(sid) + 8;
70 ZERO_STRUCTP(&t->trustee);
71 sid_copy(&t->trustee, sid);
74 /*******************************************************************
75 Reads or writes a SEC_ACE structure.
76 ********************************************************************/
78 BOOL sec_io_ace(char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
81 uint32 offset_ace_size;
86 prs_debug(ps, depth, desc, "sec_io_ace");
92 old_offset = prs_offset(ps);
94 if(!prs_uint8("type ", ps, depth, &psa->type))
97 if(!prs_uint8("flags", ps, depth, &psa->flags))
100 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
103 if(!sec_io_access("info ", &psa->info, ps, depth))
109 if(!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth))
112 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
118 /*******************************************************************
119 Create a SEC_ACL structure.
120 ********************************************************************/
122 SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
127 if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
130 dst->revision = revision;
131 dst->num_aces = num_aces;
134 /* Now we need to return a non-NULL address for the ace list even
135 if the number of aces required is zero. This is because there
136 is a distinct difference between a NULL ace and an ace with zero
137 entries in it. This is achieved by checking that num_aces is a
141 ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces))
146 for (i = 0; i < num_aces; i++) {
147 dst->ace[i] = ace_list[i]; /* Structure copy. */
148 dst->size += ace_list[i].size;
154 /*******************************************************************
155 Duplicate a SEC_ACL structure.
156 ********************************************************************/
158 SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
163 return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
166 /*******************************************************************
167 Reads or writes a SEC_ACL structure.
169 First of the xx_io_xx functions that allocates its data structures
170 for you as it reads them.
171 ********************************************************************/
173 BOOL sec_io_acl(char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
177 uint32 offset_acl_size;
185 if(UNMARSHALLING(ps) && psa == NULL) {
187 * This is a read and we must allocate the stuct to read into.
189 if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
194 prs_debug(ps, depth, desc, "sec_io_acl");
200 old_offset = prs_offset(ps);
202 if(!prs_uint16("revision", ps, depth, &psa->revision))
205 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size))
208 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
211 if (UNMARSHALLING(ps)) {
213 * Even if the num_aces is zero, allocate memory as there's a difference
214 * between a non-present DACL (allow all access) and a DACL with no ACE's
217 if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
221 for (i = 0; i < psa->num_aces; i++) {
223 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
224 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
231 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset))
237 /*******************************************************************
238 Works out the linearization size of a SEC_DESC.
239 ********************************************************************/
241 size_t sec_desc_size(SEC_DESC *psd)
247 offset = SD_HEADER_SIZE;
249 if (psd->owner_sid != NULL)
250 offset += ((sid_size(psd->owner_sid) + 3) & ~3);
252 if (psd->grp_sid != NULL)
253 offset += ((sid_size(psd->grp_sid) + 3) & ~3);
255 if (psd->sacl != NULL)
256 offset += ((psd->sacl->size + 3) & ~3);
258 if (psd->dacl != NULL)
259 offset += ((psd->dacl->size + 3) & ~3);
264 /*******************************************************************
265 Compares two SEC_ACE structures
266 ********************************************************************/
268 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
272 if (!s1 && !s2) return True;
274 /* Check top level stuff */
276 if (s1->type != s2->type || s1->flags != s2->flags ||
277 s1->info.mask != s2->info.mask) {
283 if (!sid_equal(&s1->trustee, &s2->trustee)) {
290 /*******************************************************************
291 Compares two SEC_ACL structures
292 ********************************************************************/
294 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
300 if (!s1 && !s2) return True;
301 if (!s1 || !s2) return False;
303 /* Check top level stuff */
305 if (s1->revision != s2->revision) {
306 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
307 s1->revision, s2->revision));
311 if (s1->num_aces != s2->num_aces) {
312 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
313 s1->revision, s2->revision));
317 /* The ACEs could be in any order so check each ACE in s1 against
320 for (i = 0; i < s1->num_aces; i++) {
323 for (j = 0; j < s2->num_aces; j++) {
324 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
330 if (!found) return False;
336 /*******************************************************************
337 Compares two SEC_DESC structures
338 ********************************************************************/
340 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
348 /* Check top level stuff */
350 if (s1->revision != s2->revision) {
351 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
352 s1->revision, s2->revision));
356 if (s1->type!= s2->type) {
357 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
358 s1->type, s2->type));
362 /* Check owner and group */
364 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
367 sid_to_string(str1, s1->owner_sid);
368 sid_to_string(str2, s2->owner_sid);
370 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
375 if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
378 sid_to_string(str1, s1->grp_sid);
379 sid_to_string(str2, s2->grp_sid);
381 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
386 /* Check ACLs present in one but not the other */
388 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
389 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
390 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
394 /* Sigh - we have to do it the hard way by iterating over all
395 the ACEs in the ACLs */
397 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
398 !sec_acl_equal(s1->sacl, s2->sacl)) {
399 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
404 DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
408 /*******************************************************************
409 Merge part of security descriptor old_sec in to the empty sections of
410 security descriptor new_sec.
411 ********************************************************************/
413 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
415 DOM_SID *owner_sid, *group_sid;
416 SEC_DESC_BUF *return_sdb;
417 SEC_ACL *dacl, *sacl;
418 SEC_DESC *psd = NULL;
422 /* Copy over owner and group sids. There seems to be no flag for
423 this so just check the pointer values. */
425 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
426 old_sdb->sec->owner_sid;
428 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
429 old_sdb->sec->grp_sid;
431 secdesc_type = new_sdb->sec->type;
433 /* Ignore changes to the system ACL. This has the effect of making
434 changes through the security tab audit button not sticking.
435 Perhaps in future Samba could implement these settings somehow. */
438 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
440 /* Copy across discretionary ACL */
442 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
443 dacl = new_sdb->sec->dacl;
445 dacl = old_sdb->sec->dacl;
448 /* Create new security descriptor from bits */
450 psd = make_sec_desc(ctx, new_sdb->sec->revision,
451 owner_sid, group_sid, sacl, dacl, &secdesc_size);
453 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
458 /*******************************************************************
459 Tallocs a duplicate SID.
460 ********************************************************************/
462 static DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src)
469 if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) {
476 /*******************************************************************
477 Creates a SEC_DESC structure
478 ********************************************************************/
480 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
481 DOM_SID *owner_sid, DOM_SID *grp_sid,
482 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
489 if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
492 dst->revision = revision;
493 dst->type = SEC_DESC_SELF_RELATIVE;
495 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
496 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
498 dst->off_owner_sid = 0;
499 dst->off_grp_sid = 0;
503 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
506 if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
509 if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
512 if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
518 * Work out the linearization sizes.
521 if (dst->owner_sid != NULL) {
524 offset = SD_HEADER_SIZE;
526 dst->off_owner_sid = offset;
527 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
530 if (dst->grp_sid != NULL) {
533 offset = SD_HEADER_SIZE;
535 dst->off_grp_sid = offset;
536 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
539 if (dst->sacl != NULL) {
542 offset = SD_HEADER_SIZE;
544 dst->off_sacl = offset;
545 offset += ((dst->sacl->size + 3) & ~3);
548 if (dst->dacl != NULL) {
551 offset = SD_HEADER_SIZE;
553 dst->off_dacl = offset;
554 offset += ((dst->dacl->size + 3) & ~3);
557 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
566 /*******************************************************************
567 Duplicate a SEC_DESC structure.
568 ********************************************************************/
570 SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src)
577 return make_sec_desc( ctx, src->revision,
578 src->owner_sid, src->grp_sid, src->sacl,
582 /*******************************************************************
583 Creates a SEC_DESC structure with typical defaults.
584 ********************************************************************/
586 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
587 SEC_ACL *dacl, size_t *sd_size)
589 return make_sec_desc(ctx, SEC_DESC_REVISION,
590 owner_sid, grp_sid, NULL, dacl, sd_size);
593 /*******************************************************************
594 Reads or writes a SEC_DESC structure.
595 If reading and the *ppsd = NULL, allocates the structure.
596 ********************************************************************/
598 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
601 uint32 max_offset = 0; /* after we're done, move offset to end */
610 if(UNMARSHALLING(ps)) {
611 if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
615 /* Marshalling - just ignore. */
620 prs_debug(ps, depth, desc, "sec_io_desc");
626 /* start of security descriptor stored for back-calc offset purposes */
627 old_offset = prs_offset(ps);
629 if(!prs_uint16("revision ", ps, depth, &psd->revision))
632 if(!prs_uint16("type ", ps, depth, &psd->type))
635 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
638 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
641 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
644 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
647 max_offset = MAX(max_offset, prs_offset(ps));
649 if (psd->off_owner_sid != 0) {
651 if (UNMARSHALLING(ps)) {
652 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
655 if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
659 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
665 max_offset = MAX(max_offset, prs_offset(ps));
667 if (psd->off_grp_sid != 0) {
669 if (UNMARSHALLING(ps)) {
671 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
673 if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
677 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
683 max_offset = MAX(max_offset, prs_offset(ps));
685 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
686 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
688 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
694 max_offset = MAX(max_offset, prs_offset(ps));
696 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
697 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
699 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
705 max_offset = MAX(max_offset, prs_offset(ps));
707 if(!prs_set_offset(ps, max_offset))
712 /*******************************************************************
713 Creates a SEC_DESC_BUF structure.
714 ********************************************************************/
716 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
720 if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
723 /* max buffer size (allocated size) */
724 dst->max_len = (uint32)len;
725 dst->len = (uint32)len;
727 if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
736 /*******************************************************************
737 Duplicates a SEC_DESC_BUF structure.
738 ********************************************************************/
740 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
745 return make_sec_desc_buf( ctx, src->len, src->sec);
748 /*******************************************************************
749 Reads or writes a SEC_DESC_BUF structure.
750 ********************************************************************/
752 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
765 if (UNMARSHALLING(ps) && psdb == NULL) {
766 if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
771 prs_debug(ps, depth, desc, "sec_io_desc_buf");
777 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
780 if(!prs_uint32 ("ptr ", ps, depth, &psdb->ptr))
783 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
786 old_offset = prs_offset(ps);
788 /* reading, length is non-zero; writing, descriptor is non-NULL */
789 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
790 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
797 size = prs_offset(ps) - old_offset;
798 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
801 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))