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.
28 extern int DEBUGLEVEL;
30 #define SD_HEADER_SIZE 0x14
32 /*******************************************************************
33 Sets up a SEC_ACCESS structure.
34 ********************************************************************/
36 void init_sec_access(SEC_ACCESS *t, uint32 mask)
41 /*******************************************************************
42 Reads or writes a SEC_ACCESS structure.
43 ********************************************************************/
45 BOOL sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
50 prs_debug(ps, depth, desc, "sec_io_access");
56 if(!prs_uint32("mask", ps, depth, &(t->mask)))
63 /*******************************************************************
64 Sets up a SEC_ACE structure.
65 ********************************************************************/
67 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
71 t->size = sid_size(sid) + 8;
74 ZERO_STRUCTP(&t->sid);
75 sid_copy(&t->sid, sid);
78 /*******************************************************************
79 Reads or writes a SEC_ACE structure.
80 ********************************************************************/
82 BOOL sec_io_ace(char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
85 uint32 offset_ace_size;
90 prs_debug(ps, depth, desc, "sec_io_ace");
96 old_offset = prs_offset(ps);
98 if(!prs_uint8("type ", ps, depth, &psa->type))
101 if(!prs_uint8("flags", ps, depth, &psa->flags))
104 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
107 if(!sec_io_access("info ", &psa->info, ps, depth))
113 if(!smb_io_dom_sid("sid ", &psa->sid , ps, depth))
116 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
122 /*******************************************************************
123 Create a SEC_ACL structure.
124 ********************************************************************/
126 SEC_ACL *make_sec_acl(uint16 revision, int num_aces, SEC_ACE *ace_list)
131 if((dst = (SEC_ACL *)malloc(sizeof(SEC_ACL))) == NULL)
136 dst->revision = revision;
137 dst->num_aces = num_aces;
140 if((dst->ace = (SEC_ACE *)malloc( sizeof(SEC_ACE) * num_aces )) == NULL) {
145 for (i = 0; i < num_aces; i++) {
146 dst->ace[i] = ace_list[i]; /* Structure copy. */
147 dst->size += ace_list[i].size;
153 /*******************************************************************
154 Duplicate a SEC_ACL structure.
155 ********************************************************************/
157 SEC_ACL *dup_sec_acl( SEC_ACL *src)
162 return make_sec_acl( src->revision, src->num_aces, src->ace);
165 /*******************************************************************
166 Delete a SEC_ACL structure.
167 ********************************************************************/
169 void free_sec_acl(SEC_ACL **ppsa)
173 if(ppsa == NULL || *ppsa == NULL)
177 if (psa->ace != NULL)
184 /*******************************************************************
185 Reads or writes a SEC_ACL structure.
187 First of the xx_io_xx functions that allocates its data structures
188 for you as it reads them.
189 ********************************************************************/
191 BOOL sec_io_acl(char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
195 uint32 offset_acl_size;
203 if(UNMARSHALLING(ps) && psa == NULL) {
205 * This is a read and we must allocate the stuct to read into.
207 if((psa = (SEC_ACL *)malloc(sizeof(SEC_ACL))) == NULL)
213 prs_debug(ps, depth, desc, "sec_io_acl");
219 old_offset = prs_offset(ps);
221 if(!prs_uint16("revision", ps, depth, &psa->revision))
224 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size))
227 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
230 if (UNMARSHALLING(ps) && psa->num_aces != 0) {
232 if((psa->ace = malloc(sizeof(psa->ace[0]) * psa->num_aces)) == NULL)
234 ZERO_STRUCTP(psa->ace);
237 for (i = 0; i < psa->num_aces; i++) {
239 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
240 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
247 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset))
253 /*******************************************************************
254 Works out the linearization size of a SEC_DESC.
255 ********************************************************************/
257 size_t sec_desc_size(SEC_DESC *psd)
263 offset = SD_HEADER_SIZE;
265 if (psd->owner_sid != NULL)
266 offset += ((sid_size(psd->owner_sid) + 3) & ~3);
268 if (psd->grp_sid != NULL)
269 offset += ((sid_size(psd->grp_sid) + 3) & ~3);
271 if (psd->sacl != NULL)
272 offset += ((psd->sacl->size + 3) & ~3);
274 if (psd->dacl != NULL)
275 offset += ((psd->dacl->size + 3) & ~3);
280 /*******************************************************************
281 Compares two SEC_ACE structures
282 ********************************************************************/
284 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
288 if (!s1 && !s2) return True;
290 /* Check top level stuff */
292 if (s1->type != s2->type || s1->flags != s2->flags ||
293 s1->info.mask != s2->info.mask) {
299 if (!sid_equal(&s1->sid, &s2->sid)) {
306 /*******************************************************************
307 Compares two SEC_ACL structures
308 ********************************************************************/
310 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
316 if (!s1 && !s2) return True;
318 /* Check top level stuff */
320 if (s1->revision != s2->revision) {
321 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
322 s1->revision, s2->revision));
326 if (s1->num_aces != s2->num_aces) {
327 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
328 s1->revision, s2->revision));
332 /* The ACEs could be in any order so check each ACE in s1 against
335 for (i = 0; i < s1->num_aces; i++) {
338 for (j = 0; j < s2->num_aces; j++) {
339 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
345 if (!found) return False;
351 /*******************************************************************
352 Compares two SEC_DESC structures
353 ********************************************************************/
355 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
363 /* Check top level stuff */
365 if (s1->revision != s2->revision) {
366 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
367 s1->revision, s2->revision));
371 if (s1->type!= s2->type) {
372 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
373 s1->type, s2->type));
377 /* Check owner and group */
379 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
382 sid_to_string(str1, s1->owner_sid);
383 sid_to_string(str2, s2->owner_sid);
385 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
390 if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
393 sid_to_string(str1, s1->grp_sid);
394 sid_to_string(str2, s2->grp_sid);
396 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
401 /* Check ACLs present in one but not the other */
403 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
404 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
405 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
409 /* Sigh - we have to do it the hard way by iterating over all
410 the ACEs in the ACLs */
412 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
413 !sec_acl_equal(s1->sacl, s2->sacl)) {
414 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
419 DEBUG(10, ("sec_equal(): secdescs are identical\n"));
423 /*******************************************************************
424 Merge part of security descriptor old_sec in to the empty sections of
425 security descriptor new_sec.
426 ********************************************************************/
428 SEC_DESC_BUF *sec_desc_merge(SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
430 DOM_SID *owner_sid, *group_sid;
431 SEC_DESC_BUF *return_sdb;
432 SEC_ACL *dacl, *sacl;
433 SEC_DESC *psd = NULL;
437 /* Copy over owner and group sids. There seems to be no flag for
438 this so just check the pointer values. */
440 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
441 old_sdb->sec->owner_sid;
443 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
444 old_sdb->sec->grp_sid;
446 secdesc_type = new_sdb->sec->type;
448 /* Ignore changes to the system ACL. This has the effect of making
449 changes through the security tab audit button not sticking.
450 Perhaps in future Samba could implement these settings somehow. */
453 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
455 /* Copy across discretionary ACL */
457 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
458 dacl = new_sdb->sec->dacl;
460 dacl = old_sdb->sec->dacl;
463 /* Create new security descriptor from bits */
465 psd = make_sec_desc(new_sdb->sec->revision,
466 owner_sid, group_sid, sacl, dacl, &secdesc_size);
468 return_sdb = make_sec_desc_buf(secdesc_size, psd);
475 /*******************************************************************
476 Creates a SEC_DESC structure
477 ********************************************************************/
479 SEC_DESC *make_sec_desc(uint16 revision,
480 DOM_SID *owner_sid, DOM_SID *grp_sid,
481 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
488 if(( dst = (SEC_DESC *)malloc(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(owner_sid)) == NULL))
507 if(grp_sid && ((dst->grp_sid = sid_dup(grp_sid)) == NULL))
510 if(sacl && ((dst->sacl = dup_sec_acl(sacl)) == NULL))
513 if(dacl && ((dst->dacl = dup_sec_acl(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 += ((sacl->size + 3) & ~3);
549 if (dst->dacl != NULL) {
552 offset = SD_HEADER_SIZE;
554 dst->off_dacl = offset;
555 offset += ((dacl->size + 3) & ~3);
558 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
568 /*******************************************************************
569 Duplicate a SEC_DESC structure.
570 ********************************************************************/
572 SEC_DESC *dup_sec_desc( SEC_DESC *src)
579 return make_sec_desc( src->revision,
580 src->owner_sid, src->grp_sid, src->sacl,
584 /*******************************************************************
585 Deletes a SEC_DESC structure
586 ********************************************************************/
588 void free_sec_desc(SEC_DESC **ppsd)
592 if(ppsd == NULL || *ppsd == NULL)
597 free_sec_acl(&psd->dacl);
598 free_sec_acl(&psd->dacl);
599 free(psd->owner_sid);
605 /*******************************************************************
606 Creates a SEC_DESC structure with typical defaults.
607 ********************************************************************/
609 SEC_DESC *make_standard_sec_desc(DOM_SID *owner_sid, DOM_SID *grp_sid,
610 SEC_ACL *dacl, size_t *sd_size)
612 return make_sec_desc(SEC_DESC_REVISION,
613 owner_sid, grp_sid, NULL, dacl, sd_size);
616 /*******************************************************************
617 Reads or writes a SEC_DESC structure.
618 If reading and the *ppsd = NULL, allocates the structure.
619 ********************************************************************/
621 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
624 uint32 max_offset = 0; /* after we're done, move offset to end */
633 if(UNMARSHALLING(ps)) {
634 if((psd = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
639 /* Marshalling - just ignore. */
644 prs_debug(ps, depth, desc, "sec_io_desc");
650 /* start of security descriptor stored for back-calc offset purposes */
651 old_offset = prs_offset(ps);
653 if(!prs_uint16("revision ", ps, depth, &psd->revision))
656 if(!prs_uint16("type ", ps, depth, &psd->type))
659 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
662 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
665 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
668 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
671 max_offset = MAX(max_offset, prs_offset(ps));
673 if (psd->off_owner_sid != 0) {
675 if (UNMARSHALLING(ps)) {
676 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
679 if((psd->owner_sid = malloc(sizeof(*psd->owner_sid))) == NULL)
681 ZERO_STRUCTP(psd->owner_sid);
684 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
690 max_offset = MAX(max_offset, prs_offset(ps));
692 if (psd->off_grp_sid != 0) {
694 if (UNMARSHALLING(ps)) {
696 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
698 if((psd->grp_sid = malloc(sizeof(*psd->grp_sid))) == NULL)
700 ZERO_STRUCTP(psd->grp_sid);
703 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
709 max_offset = MAX(max_offset, prs_offset(ps));
711 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
712 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
714 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
720 max_offset = MAX(max_offset, prs_offset(ps));
722 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
723 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
725 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
731 max_offset = MAX(max_offset, prs_offset(ps));
733 if(!prs_set_offset(ps, max_offset))
738 /*******************************************************************
739 Creates a SEC_DESC_BUF structure.
740 ********************************************************************/
742 SEC_DESC_BUF *make_sec_desc_buf(size_t len, SEC_DESC *sec_desc)
746 if((dst = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
751 /* max buffer size (allocated size) */
752 dst->max_len = (uint32)len;
753 dst->len = (uint32)len;
755 if(sec_desc && ((dst->sec = dup_sec_desc(sec_desc)) == NULL)) {
756 free_sec_desc_buf(&dst);
763 /*******************************************************************
764 Duplicates a SEC_DESC_BUF structure.
765 ********************************************************************/
767 SEC_DESC_BUF *dup_sec_desc_buf(SEC_DESC_BUF *src)
772 return make_sec_desc_buf( src->len, src->sec);
775 /*******************************************************************
776 Deletes a SEC_DESC_BUF structure.
777 ********************************************************************/
779 void free_sec_desc_buf(SEC_DESC_BUF **ppsdb)
783 if(ppsdb == NULL || *ppsdb == NULL)
787 free_sec_desc(&psdb->sec);
793 /*******************************************************************
794 Reads or writes a SEC_DESC_BUF structure.
795 ********************************************************************/
797 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
810 if (UNMARSHALLING(ps) && psdb == NULL) {
811 if((psdb = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
817 prs_debug(ps, depth, desc, "sec_io_desc_buf");
823 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
826 if(!prs_uint32 ("undoc ", ps, depth, &psdb->undoc))
829 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
832 old_offset = prs_offset(ps);
834 /* reading, length is non-zero; writing, descriptor is non-NULL */
835 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
836 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
843 size = prs_offset(ps) - old_offset;
844 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
847 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))