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)
212 prs_debug(ps, depth, desc, "sec_io_acl");
218 old_offset = prs_offset(ps);
220 if(!prs_uint16("revision", ps, depth, &psa->revision))
223 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size))
226 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
229 if (UNMARSHALLING(ps) && psa->num_aces != 0) {
231 if((psa->ace = malloc(sizeof(psa->ace[0]) * psa->num_aces)) == NULL)
235 for (i = 0; i < psa->num_aces; i++) {
237 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
238 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
245 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset))
251 /*******************************************************************
252 Works out the linearization size of a SEC_DESC.
253 ********************************************************************/
255 size_t sec_desc_size(SEC_DESC *psd)
261 offset = SD_HEADER_SIZE;
263 if (psd->owner_sid != NULL)
264 offset += ((sid_size(psd->owner_sid) + 3) & ~3);
266 if (psd->grp_sid != NULL)
267 offset += ((sid_size(psd->grp_sid) + 3) & ~3);
269 if (psd->sacl != NULL)
270 offset += ((psd->sacl->size + 3) & ~3);
272 if (psd->dacl != NULL)
273 offset += ((psd->dacl->size + 3) & ~3);
278 /*******************************************************************
279 Compares two SEC_ACE structures
280 ********************************************************************/
282 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
286 if (!s1 && !s2) return True;
288 /* Check top level stuff */
290 if (s1->type != s2->type || s1->flags != s2->flags ||
291 s1->info.mask != s2->info.mask) {
297 if (!sid_equal(&s1->sid, &s2->sid)) {
304 /*******************************************************************
305 Compares two SEC_ACL structures
306 ********************************************************************/
308 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
314 if (!s1 && !s2) return True;
316 /* Check top level stuff */
318 if (s1->revision != s2->revision) {
319 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
320 s1->revision, s2->revision));
324 if (s1->num_aces != s2->num_aces) {
325 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
326 s1->revision, s2->revision));
330 /* The ACEs could be in any order so check each ACE in s1 against
333 for (i = 0; i < s1->num_aces; i++) {
336 for (j = 0; j < s2->num_aces; j++) {
337 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
343 if (!found) return False;
349 /*******************************************************************
350 Compares two SEC_DESC structures
351 ********************************************************************/
353 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
361 /* Check top level stuff */
363 if (s1->revision != s2->revision) {
364 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
365 s1->revision, s2->revision));
369 if (s1->type!= s2->type) {
370 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
371 s1->type, s2->type));
375 /* Check owner and group */
377 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
380 sid_to_string(str1, s1->owner_sid);
381 sid_to_string(str2, s2->owner_sid);
383 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
388 if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
391 sid_to_string(str1, s1->grp_sid);
392 sid_to_string(str2, s2->grp_sid);
394 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
399 /* Check ACLs present in one but not the other */
401 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
402 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
403 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
407 /* Sigh - we have to do it the hard way by iterating over all
408 the ACEs in the ACLs */
410 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
411 !sec_acl_equal(s1->sacl, s2->sacl)) {
412 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
417 DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
421 /*******************************************************************
422 Merge part of security descriptor old_sec in to the empty sections of
423 security descriptor new_sec.
424 ********************************************************************/
426 SEC_DESC_BUF *sec_desc_merge(SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
428 DOM_SID *owner_sid, *group_sid;
429 SEC_DESC_BUF *return_sdb;
430 SEC_ACL *dacl, *sacl;
431 SEC_DESC *psd = NULL;
435 /* Copy over owner and group sids. There seems to be no flag for
436 this so just check the pointer values. */
438 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
439 old_sdb->sec->owner_sid;
441 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
442 old_sdb->sec->grp_sid;
444 secdesc_type = new_sdb->sec->type;
446 /* Ignore changes to the system ACL. This has the effect of making
447 changes through the security tab audit button not sticking.
448 Perhaps in future Samba could implement these settings somehow. */
451 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
453 /* Copy across discretionary ACL */
455 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
456 dacl = new_sdb->sec->dacl;
458 dacl = old_sdb->sec->dacl;
461 /* Create new security descriptor from bits */
463 psd = make_sec_desc(new_sdb->sec->revision,
464 owner_sid, group_sid, sacl, dacl, &secdesc_size);
466 return_sdb = make_sec_desc_buf(secdesc_size, psd);
473 /*******************************************************************
474 Creates a SEC_DESC structure
475 ********************************************************************/
477 SEC_DESC *make_sec_desc(uint16 revision,
478 DOM_SID *owner_sid, DOM_SID *grp_sid,
479 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
486 if(( dst = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
491 dst->revision = revision;
492 dst->type = SEC_DESC_SELF_RELATIVE;
494 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
495 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
497 dst->off_owner_sid = 0;
498 dst->off_grp_sid = 0;
502 if(owner_sid && ((dst->owner_sid = sid_dup(owner_sid)) == NULL))
505 if(grp_sid && ((dst->grp_sid = sid_dup(grp_sid)) == NULL))
508 if(sacl && ((dst->sacl = dup_sec_acl(sacl)) == NULL))
511 if(dacl && ((dst->dacl = dup_sec_acl(dacl)) == NULL))
517 * Work out the linearization sizes.
520 if (dst->owner_sid != NULL) {
523 offset = SD_HEADER_SIZE;
525 dst->off_owner_sid = offset;
526 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
529 if (dst->grp_sid != NULL) {
532 offset = SD_HEADER_SIZE;
534 dst->off_grp_sid = offset;
535 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
538 if (dst->sacl != NULL) {
541 offset = SD_HEADER_SIZE;
543 dst->off_sacl = offset;
544 offset += ((sacl->size + 3) & ~3);
547 if (dst->dacl != NULL) {
550 offset = SD_HEADER_SIZE;
552 dst->off_dacl = offset;
553 offset += ((dacl->size + 3) & ~3);
556 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
566 /*******************************************************************
567 Duplicate a SEC_DESC structure.
568 ********************************************************************/
570 SEC_DESC *dup_sec_desc( SEC_DESC *src)
577 return make_sec_desc( src->revision,
578 src->owner_sid, src->grp_sid, src->sacl,
582 /*******************************************************************
583 Deletes a SEC_DESC structure
584 ********************************************************************/
586 void free_sec_desc(SEC_DESC **ppsd)
590 if(ppsd == NULL || *ppsd == NULL)
595 free_sec_acl(&psd->dacl);
596 free_sec_acl(&psd->sacl);
597 free(psd->owner_sid);
603 /*******************************************************************
604 Creates a SEC_DESC structure with typical defaults.
605 ********************************************************************/
607 SEC_DESC *make_standard_sec_desc(DOM_SID *owner_sid, DOM_SID *grp_sid,
608 SEC_ACL *dacl, size_t *sd_size)
610 return make_sec_desc(SEC_DESC_REVISION,
611 owner_sid, grp_sid, NULL, dacl, sd_size);
614 /*******************************************************************
615 Reads or writes a SEC_DESC structure.
616 If reading and the *ppsd = NULL, allocates the structure.
617 ********************************************************************/
619 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
622 uint32 max_offset = 0; /* after we're done, move offset to end */
631 if(UNMARSHALLING(ps)) {
632 if((psd = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
636 /* Marshalling - just ignore. */
641 prs_debug(ps, depth, desc, "sec_io_desc");
647 /* start of security descriptor stored for back-calc offset purposes */
648 old_offset = prs_offset(ps);
650 if(!prs_uint16("revision ", ps, depth, &psd->revision))
653 if(!prs_uint16("type ", ps, depth, &psd->type))
656 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
659 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
662 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
665 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
668 max_offset = MAX(max_offset, prs_offset(ps));
670 if (psd->off_owner_sid != 0) {
672 if (UNMARSHALLING(ps)) {
673 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
676 if((psd->owner_sid = malloc(sizeof(*psd->owner_sid))) == NULL)
680 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
686 max_offset = MAX(max_offset, prs_offset(ps));
688 if (psd->off_grp_sid != 0) {
690 if (UNMARSHALLING(ps)) {
692 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
694 if((psd->grp_sid = malloc(sizeof(*psd->grp_sid))) == NULL)
698 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
704 max_offset = MAX(max_offset, prs_offset(ps));
706 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
707 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
709 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
715 max_offset = MAX(max_offset, prs_offset(ps));
717 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
718 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
720 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
726 max_offset = MAX(max_offset, prs_offset(ps));
728 if(!prs_set_offset(ps, max_offset))
733 /*******************************************************************
734 Creates a SEC_DESC_BUF structure.
735 ********************************************************************/
737 SEC_DESC_BUF *make_sec_desc_buf(size_t len, SEC_DESC *sec_desc)
741 if((dst = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
746 /* max buffer size (allocated size) */
747 dst->max_len = (uint32)len;
748 dst->len = (uint32)len;
750 if(sec_desc && ((dst->sec = dup_sec_desc(sec_desc)) == NULL)) {
751 free_sec_desc_buf(&dst);
758 /*******************************************************************
759 Duplicates a SEC_DESC_BUF structure.
760 ********************************************************************/
762 SEC_DESC_BUF *dup_sec_desc_buf(SEC_DESC_BUF *src)
767 return make_sec_desc_buf( src->len, src->sec);
770 /*******************************************************************
771 Deletes a SEC_DESC_BUF structure.
772 ********************************************************************/
774 void free_sec_desc_buf(SEC_DESC_BUF **ppsdb)
778 if(ppsdb == NULL || *ppsdb == NULL)
782 free_sec_desc(&psdb->sec);
788 /*******************************************************************
789 Reads or writes a SEC_DESC_BUF structure.
790 ********************************************************************/
792 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
805 if (UNMARSHALLING(ps) && psdb == NULL) {
806 if((psdb = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
811 prs_debug(ps, depth, desc, "sec_io_desc_buf");
817 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
820 if(!prs_uint32 ("undoc ", ps, depth, &psdb->undoc))
823 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
826 old_offset = prs_offset(ps);
828 /* reading, length is non-zero; writing, descriptor is non-NULL */
829 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
830 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
837 size = prs_offset(ps) - old_offset;
838 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
841 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))