2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-1998,
6 * Copyright (C) Jeremy R. Allison 1995-1998
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
8 * Copyright (C) Paul Ashton 1997-1998.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define SD_HEADER_SIZE 0x14
29 /*******************************************************************
30 Sets up a SEC_ACCESS structure.
31 ********************************************************************/
33 void init_sec_access(SEC_ACCESS *t, uint32 mask)
38 /*******************************************************************
39 Reads or writes a SEC_ACCESS structure.
40 ********************************************************************/
42 BOOL sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
47 prs_debug(ps, depth, desc, "sec_io_access");
53 if(!prs_uint32("mask", ps, depth, &(t->mask)))
60 /*******************************************************************
61 Sets up a SEC_ACE structure.
62 ********************************************************************/
64 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
68 t->size = sid_size(sid) + 8;
71 ZERO_STRUCTP(&t->sid);
72 sid_copy(&t->sid, sid);
75 /*******************************************************************
76 Reads or writes a SEC_ACE structure.
77 ********************************************************************/
79 BOOL sec_io_ace(char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
82 uint32 offset_ace_size;
87 prs_debug(ps, depth, desc, "sec_io_ace");
93 old_offset = prs_offset(ps);
95 if(!prs_uint8("type ", ps, depth, &psa->type))
98 if(!prs_uint8("flags", ps, depth, &psa->flags))
101 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
104 if(!sec_io_access("info ", &psa->info, ps, depth))
110 if(!smb_io_dom_sid("sid ", &psa->sid , ps, depth))
113 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
119 /*******************************************************************
120 Create a SEC_ACL structure.
121 ********************************************************************/
123 SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
128 if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
131 dst->revision = revision;
132 dst->num_aces = num_aces;
135 /* Now we need to return a non-NULL address for the ace list even
136 if the number of aces required is zero. This is because there
137 is a distinct difference between a NULL ace and an ace with zero
138 entries in it. This is achieved by checking that num_aces is a
142 ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces))
147 for (i = 0; i < num_aces; i++) {
148 dst->ace[i] = ace_list[i]; /* Structure copy. */
149 dst->size += ace_list[i].size;
155 /*******************************************************************
156 Duplicate a SEC_ACL structure.
157 ********************************************************************/
159 SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
164 return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
167 /*******************************************************************
168 Reads or writes a SEC_ACL structure.
170 First of the xx_io_xx functions that allocates its data structures
171 for you as it reads them.
172 ********************************************************************/
174 BOOL sec_io_acl(char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
178 uint32 offset_acl_size;
186 if(UNMARSHALLING(ps) && psa == NULL) {
188 * This is a read and we must allocate the stuct to read into.
190 if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
195 prs_debug(ps, depth, desc, "sec_io_acl");
201 old_offset = prs_offset(ps);
203 if(!prs_uint16("revision", ps, depth, &psa->revision))
206 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size))
209 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
212 if (UNMARSHALLING(ps)) {
214 * Even if the num_aces is zero, allocate memory as there's a difference
215 * between a non-present DACL (allow all access) and a DACL with no ACE's
218 if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
222 for (i = 0; i < psa->num_aces; i++) {
224 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
225 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
232 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset))
238 /*******************************************************************
239 Works out the linearization size of a SEC_DESC.
240 ********************************************************************/
242 size_t sec_desc_size(SEC_DESC *psd)
248 offset = SD_HEADER_SIZE;
250 if (psd->owner_sid != NULL)
251 offset += ((sid_size(psd->owner_sid) + 3) & ~3);
253 if (psd->grp_sid != NULL)
254 offset += ((sid_size(psd->grp_sid) + 3) & ~3);
256 if (psd->sacl != NULL)
257 offset += ((psd->sacl->size + 3) & ~3);
259 if (psd->dacl != NULL)
260 offset += ((psd->dacl->size + 3) & ~3);
265 /*******************************************************************
266 Compares two SEC_ACE structures
267 ********************************************************************/
269 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
273 if (!s1 && !s2) return True;
275 /* Check top level stuff */
277 if (s1->type != s2->type || s1->flags != s2->flags ||
278 s1->info.mask != s2->info.mask) {
284 if (!sid_equal(&s1->sid, &s2->sid)) {
291 /*******************************************************************
292 Compares two SEC_ACL structures
293 ********************************************************************/
295 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
301 if (!s1 && !s2) return True;
302 if (!s1 || !s2) return False;
304 /* Check top level stuff */
306 if (s1->revision != s2->revision) {
307 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
308 s1->revision, s2->revision));
312 if (s1->num_aces != s2->num_aces) {
313 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
314 s1->revision, s2->revision));
318 /* The ACEs could be in any order so check each ACE in s1 against
321 for (i = 0; i < s1->num_aces; i++) {
324 for (j = 0; j < s2->num_aces; j++) {
325 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
331 if (!found) return False;
337 /*******************************************************************
338 Compares two SEC_DESC structures
339 ********************************************************************/
341 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
349 /* Check top level stuff */
351 if (s1->revision != s2->revision) {
352 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
353 s1->revision, s2->revision));
357 if (s1->type!= s2->type) {
358 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
359 s1->type, s2->type));
363 /* Check owner and group */
365 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
368 sid_to_string(str1, s1->owner_sid);
369 sid_to_string(str2, s2->owner_sid);
371 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
376 if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
379 sid_to_string(str1, s1->grp_sid);
380 sid_to_string(str2, s2->grp_sid);
382 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
387 /* Check ACLs present in one but not the other */
389 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
390 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
391 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
395 /* Sigh - we have to do it the hard way by iterating over all
396 the ACEs in the ACLs */
398 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
399 !sec_acl_equal(s1->sacl, s2->sacl)) {
400 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
405 DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
409 /*******************************************************************
410 Merge part of security descriptor old_sec in to the empty sections of
411 security descriptor new_sec.
412 ********************************************************************/
414 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
416 DOM_SID *owner_sid, *group_sid;
417 SEC_DESC_BUF *return_sdb;
418 SEC_ACL *dacl, *sacl;
419 SEC_DESC *psd = NULL;
423 /* Copy over owner and group sids. There seems to be no flag for
424 this so just check the pointer values. */
426 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
427 old_sdb->sec->owner_sid;
429 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
430 old_sdb->sec->grp_sid;
432 secdesc_type = new_sdb->sec->type;
434 /* Ignore changes to the system ACL. This has the effect of making
435 changes through the security tab audit button not sticking.
436 Perhaps in future Samba could implement these settings somehow. */
439 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
441 /* Copy across discretionary ACL */
443 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
444 dacl = new_sdb->sec->dacl;
446 dacl = old_sdb->sec->dacl;
449 /* Create new security descriptor from bits */
451 psd = make_sec_desc(ctx, new_sdb->sec->revision,
452 owner_sid, group_sid, sacl, dacl, &secdesc_size);
454 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
459 /*******************************************************************
460 Tallocs a duplicate SID.
461 ********************************************************************/
463 static DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src)
470 if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) {
477 /*******************************************************************
478 Creates a SEC_DESC structure
479 ********************************************************************/
481 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
482 DOM_SID *owner_sid, DOM_SID *grp_sid,
483 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
490 if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
493 dst->revision = revision;
494 dst->type = SEC_DESC_SELF_RELATIVE;
496 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
497 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
499 dst->off_owner_sid = 0;
500 dst->off_grp_sid = 0;
504 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
507 if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
510 if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
513 if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
519 * Work out the linearization sizes.
522 if (dst->owner_sid != NULL) {
525 offset = SD_HEADER_SIZE;
527 dst->off_owner_sid = offset;
528 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
531 if (dst->grp_sid != NULL) {
534 offset = SD_HEADER_SIZE;
536 dst->off_grp_sid = offset;
537 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
540 if (dst->sacl != NULL) {
543 offset = SD_HEADER_SIZE;
545 dst->off_sacl = offset;
546 offset += ((dst->sacl->size + 3) & ~3);
549 if (dst->dacl != NULL) {
552 offset = SD_HEADER_SIZE;
554 dst->off_dacl = offset;
555 offset += ((dst->dacl->size + 3) & ~3);
558 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
567 /*******************************************************************
568 Duplicate a SEC_DESC structure.
569 ********************************************************************/
571 SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src)
578 return make_sec_desc( ctx, src->revision,
579 src->owner_sid, src->grp_sid, src->sacl,
583 /*******************************************************************
584 Creates a SEC_DESC structure with typical defaults.
585 ********************************************************************/
587 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
588 SEC_ACL *dacl, size_t *sd_size)
590 return make_sec_desc(ctx, SEC_DESC_REVISION,
591 owner_sid, grp_sid, NULL, dacl, sd_size);
594 /*******************************************************************
595 Reads or writes a SEC_DESC structure.
596 If reading and the *ppsd = NULL, allocates the structure.
597 ********************************************************************/
599 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
602 uint32 max_offset = 0; /* after we're done, move offset to end */
611 if(UNMARSHALLING(ps)) {
612 if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
616 /* Marshalling - just ignore. */
621 prs_debug(ps, depth, desc, "sec_io_desc");
627 /* start of security descriptor stored for back-calc offset purposes */
628 old_offset = prs_offset(ps);
630 if(!prs_uint16("revision ", ps, depth, &psd->revision))
633 if(!prs_uint16("type ", ps, depth, &psd->type))
636 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
639 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
642 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
645 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
648 max_offset = MAX(max_offset, prs_offset(ps));
650 if (psd->off_owner_sid != 0) {
652 if (UNMARSHALLING(ps)) {
653 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
656 if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
660 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
666 max_offset = MAX(max_offset, prs_offset(ps));
668 if (psd->off_grp_sid != 0) {
670 if (UNMARSHALLING(ps)) {
672 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
674 if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
678 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
684 max_offset = MAX(max_offset, prs_offset(ps));
686 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
687 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
689 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
695 max_offset = MAX(max_offset, prs_offset(ps));
697 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
698 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
700 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
706 max_offset = MAX(max_offset, prs_offset(ps));
708 if(!prs_set_offset(ps, max_offset))
713 /*******************************************************************
714 Creates a SEC_DESC_BUF structure.
715 ********************************************************************/
717 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
721 if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
724 /* max buffer size (allocated size) */
725 dst->max_len = (uint32)len;
726 dst->len = (uint32)len;
728 if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
737 /*******************************************************************
738 Duplicates a SEC_DESC_BUF structure.
739 ********************************************************************/
741 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
746 return make_sec_desc_buf( ctx, src->len, src->sec);
749 /*******************************************************************
750 Reads or writes a SEC_DESC_BUF structure.
751 ********************************************************************/
753 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
766 if (UNMARSHALLING(ps) && psdb == NULL) {
767 if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
772 prs_debug(ps, depth, desc, "sec_io_desc_buf");
778 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
781 if(!prs_uint32 ("ptr ", ps, depth, &psdb->ptr))
784 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
787 old_offset = prs_offset(ps);
789 /* reading, length is non-zero; writing, descriptor is non-NULL */
790 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
791 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
798 size = prs_offset(ps) - old_offset;
799 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
802 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))