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 || s1->num_aces != s2->num_aces) {
324 /* The ACEs could be in any order so check each ACE in s1 against
327 for (i = 0; i < s1->num_aces; i++) {
330 for (j = 0; j < s2->num_aces; j++) {
331 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
337 if (!found) return False;
343 /*******************************************************************
344 Compares two SEC_DESC structures
345 ********************************************************************/
347 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
355 /* Check top level stuff */
357 if (s1->revision != s2->revision || s1->type != s2->type) {
358 DEBUG(10, ("sec_desc_equal(): revision/type not equal\n"));
362 /* Check owner and group */
364 if (!sid_equal(s1->owner_sid, s2->owner_sid) ||
365 !sid_equal(s1->grp_sid, s2->grp_sid)) {
366 DEBUG(10, ("sec_desc_equal(): owner/group not equal\n"));
370 /* Check ACLs present in one but not the other */
372 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
373 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
374 DEBUG(10, ("sec_desc_equal(): dacl/sacl not equal\n"));
378 /* Sigh - we have to do it the hard way by iterating over all
379 the ACEs in the ACLs */
381 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
382 !sec_acl_equal(s1->sacl, s2->sacl)) {
383 DEBUG(10, ("sec_desc_equal(): dacl/dacl list not equal\n"));
388 DEBUG(10, ("sec_equal(): secdescs are identical\n"));
392 /*******************************************************************
393 Merge part of security descriptor old_sec in to the empty sections of
394 security descriptor new_sec.
395 ********************************************************************/
397 SEC_DESC_BUF *sec_desc_merge(SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
399 DOM_SID *owner_sid, *group_sid;
400 SEC_DESC_BUF *return_sdb;
401 SEC_ACL *dacl, *sacl;
402 SEC_DESC *psd = NULL;
406 /* Copy over owner and group sids. There seems to be no flag for
407 this so just check the pointer values. */
409 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
410 old_sdb->sec->owner_sid;
412 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
413 old_sdb->sec->grp_sid;
415 secdesc_type = new_sdb->sec->type;
417 /* Ignore changes to the system ACL. This has the effect of making
418 changes through the security tab audit button not sticking.
419 Perhaps in future Samba could implement these settings somehow. */
422 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
424 /* Copy across discretionary ACL */
426 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
427 dacl = new_sdb->sec->dacl;
429 dacl = old_sdb->sec->dacl;
432 /* Create new security descriptor from bits */
434 psd = make_sec_desc(new_sdb->sec->revision,
435 owner_sid, group_sid, sacl, dacl, &secdesc_size);
437 return_sdb = make_sec_desc_buf(secdesc_size, psd);
444 /*******************************************************************
445 Creates a SEC_DESC structure
446 ********************************************************************/
448 SEC_DESC *make_sec_desc(uint16 revision,
449 DOM_SID *owner_sid, DOM_SID *grp_sid,
450 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
457 if(( dst = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
462 dst->revision = revision;
463 dst->type = SEC_DESC_SELF_RELATIVE;
465 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
466 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
468 dst->off_owner_sid = 0;
469 dst->off_grp_sid = 0;
473 if(owner_sid && ((dst->owner_sid = sid_dup(owner_sid)) == NULL))
476 if(grp_sid && ((dst->grp_sid = sid_dup(grp_sid)) == NULL))
479 if(sacl && ((dst->sacl = dup_sec_acl(sacl)) == NULL))
482 if(dacl && ((dst->dacl = dup_sec_acl(dacl)) == NULL))
488 * Work out the linearization sizes.
491 if (dst->owner_sid != NULL) {
494 offset = SD_HEADER_SIZE;
496 dst->off_owner_sid = offset;
497 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
500 if (dst->grp_sid != NULL) {
503 offset = SD_HEADER_SIZE;
505 dst->off_grp_sid = offset;
506 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
509 if (dst->sacl != NULL) {
512 offset = SD_HEADER_SIZE;
514 dst->off_sacl = offset;
515 offset += ((sacl->size + 3) & ~3);
518 if (dst->dacl != NULL) {
521 offset = SD_HEADER_SIZE;
523 dst->off_dacl = offset;
524 offset += ((dacl->size + 3) & ~3);
527 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
537 /*******************************************************************
538 Duplicate a SEC_DESC structure.
539 ********************************************************************/
541 SEC_DESC *dup_sec_desc( SEC_DESC *src)
548 return make_sec_desc( src->revision,
549 src->owner_sid, src->grp_sid, src->sacl,
553 /*******************************************************************
554 Deletes a SEC_DESC structure
555 ********************************************************************/
557 void free_sec_desc(SEC_DESC **ppsd)
561 if(ppsd == NULL || *ppsd == NULL)
566 free_sec_acl(&psd->dacl);
567 free_sec_acl(&psd->dacl);
568 free(psd->owner_sid);
574 /*******************************************************************
575 Creates a SEC_DESC structure with typical defaults.
576 ********************************************************************/
578 SEC_DESC *make_standard_sec_desc(DOM_SID *owner_sid, DOM_SID *grp_sid,
579 SEC_ACL *dacl, size_t *sd_size)
581 return make_sec_desc(SEC_DESC_REVISION,
582 owner_sid, grp_sid, NULL, dacl, sd_size);
585 /*******************************************************************
586 Reads or writes a SEC_DESC structure.
587 If reading and the *ppsd = NULL, allocates the structure.
588 ********************************************************************/
590 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
593 uint32 max_offset = 0; /* after we're done, move offset to end */
602 if(UNMARSHALLING(ps)) {
603 if((psd = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
608 /* Marshalling - just ignore. */
613 prs_debug(ps, depth, desc, "sec_io_desc");
619 /* start of security descriptor stored for back-calc offset purposes */
620 old_offset = prs_offset(ps);
622 if(!prs_uint16("revision ", ps, depth, &psd->revision))
625 if(!prs_uint16("type ", ps, depth, &psd->type))
628 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
631 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
634 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
637 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
640 max_offset = MAX(max_offset, prs_offset(ps));
642 if (psd->off_owner_sid != 0) {
644 if (UNMARSHALLING(ps)) {
645 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
648 if((psd->owner_sid = malloc(sizeof(*psd->owner_sid))) == NULL)
650 ZERO_STRUCTP(psd->owner_sid);
653 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
659 max_offset = MAX(max_offset, prs_offset(ps));
661 if (psd->off_grp_sid != 0) {
663 if (UNMARSHALLING(ps)) {
665 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
667 if((psd->grp_sid = malloc(sizeof(*psd->grp_sid))) == NULL)
669 ZERO_STRUCTP(psd->grp_sid);
672 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
678 max_offset = MAX(max_offset, prs_offset(ps));
680 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
681 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
683 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
689 max_offset = MAX(max_offset, prs_offset(ps));
691 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
692 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
694 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
700 max_offset = MAX(max_offset, prs_offset(ps));
702 if(!prs_set_offset(ps, max_offset))
707 /*******************************************************************
708 Creates a SEC_DESC_BUF structure.
709 ********************************************************************/
711 SEC_DESC_BUF *make_sec_desc_buf(size_t len, SEC_DESC *sec_desc)
715 if((dst = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
720 /* max buffer size (allocated size) */
721 dst->max_len = (uint32)len;
722 dst->len = (uint32)len;
724 if(sec_desc && ((dst->sec = dup_sec_desc(sec_desc)) == NULL)) {
725 free_sec_desc_buf(&dst);
732 /*******************************************************************
733 Duplicates a SEC_DESC_BUF structure.
734 ********************************************************************/
736 SEC_DESC_BUF *dup_sec_desc_buf(SEC_DESC_BUF *src)
741 return make_sec_desc_buf( src->len, src->sec);
744 /*******************************************************************
745 Deletes a SEC_DESC_BUF structure.
746 ********************************************************************/
748 void free_sec_desc_buf(SEC_DESC_BUF **ppsdb)
752 if(ppsdb == NULL || *ppsdb == NULL)
756 free_sec_desc(&psdb->sec);
762 /*******************************************************************
763 Reads or writes a SEC_DESC_BUF structure.
764 ********************************************************************/
766 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
779 if (UNMARSHALLING(ps) && psdb == NULL) {
780 if((psdb = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
786 prs_debug(ps, depth, desc, "sec_io_desc_buf");
792 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
795 if(!prs_uint32 ("undoc ", ps, depth, &psdb->undoc))
798 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
801 old_offset = prs_offset(ps);
803 /* reading, length is non-zero; writing, descriptor is non-NULL */
804 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
805 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
812 size = prs_offset(ps) - old_offset;
813 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
816 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))