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)
351 if (!s1 && !s2) return True;
353 /* Check top level stuff */
355 if (s1->revision != s2->revision || s1->type != s2->type) {
359 /* Check owner and group */
361 if (!sid_equal(s1->owner_sid, s2->owner_sid) ||
362 !sid_equal(s1->grp_sid, s2->grp_sid)) {
366 /* Check ACLs present in one but not the other */
368 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
369 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
373 /* Sigh - we have to do it the hard way by iterating over all
374 the ACEs in the ACLs */
376 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
377 !sec_acl_equal(s1->sacl, s2->sacl)) {
384 /*******************************************************************
385 Merge part of security descriptor old_sec in to the empty sections of
386 security descriptor new_sec.
387 ********************************************************************/
389 SEC_DESC_BUF *sec_desc_merge(SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
391 DOM_SID *owner_sid, *group_sid;
392 SEC_DESC_BUF *return_sdb;
393 SEC_ACL *dacl, *sacl;
394 SEC_DESC *psd = NULL;
398 /* Copy over owner and group sids. There seems to be no flag for
399 this so just check the pointer values. */
401 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
402 old_sdb->sec->owner_sid;
404 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
405 old_sdb->sec->grp_sid;
407 secdesc_type = new_sdb->sec->type;
409 /* Ignore changes to the system ACL. This has the effect of making
410 changes through the security tab audit button not sticking.
411 Perhaps in future Samba could implement these settings somehow. */
414 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
416 /* Copy across discretionary ACL */
418 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
419 dacl = new_sdb->sec->dacl;
421 dacl = old_sdb->sec->dacl;
422 secdesc_type |= SEC_DESC_DACL_PRESENT;
425 /* Create new security descriptor from bits */
427 psd = make_sec_desc(new_sdb->sec->revision, secdesc_type,
428 owner_sid, group_sid, sacl, dacl, &secdesc_size);
430 return_sdb = make_sec_desc_buf(secdesc_size, psd);
437 /*******************************************************************
438 Creates a SEC_DESC structure
439 ********************************************************************/
441 SEC_DESC *make_sec_desc(uint16 revision, uint16 type,
442 DOM_SID *owner_sid, DOM_SID *grp_sid,
443 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
450 if(( dst = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
455 dst->revision = revision;
458 dst->off_owner_sid = 0;
459 dst->off_grp_sid = 0;
463 if(owner_sid && ((dst->owner_sid = sid_dup(owner_sid)) == NULL))
466 if(grp_sid && ((dst->grp_sid = sid_dup(grp_sid)) == NULL))
469 if(sacl && ((dst->sacl = dup_sec_acl(sacl)) == NULL))
472 if(dacl && ((dst->dacl = dup_sec_acl(dacl)) == NULL))
478 * Work out the linearization sizes.
481 if (dst->owner_sid != NULL) {
484 offset = SD_HEADER_SIZE;
486 dst->off_owner_sid = offset;
487 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
490 if (dst->grp_sid != NULL) {
493 offset = SD_HEADER_SIZE;
495 dst->off_grp_sid = offset;
496 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
499 if (dst->sacl != NULL) {
502 offset = SD_HEADER_SIZE;
504 dst->off_sacl = offset;
505 offset += ((sacl->size + 3) & ~3);
508 if (dst->dacl != NULL) {
511 offset = SD_HEADER_SIZE;
513 dst->off_dacl = offset;
514 offset += ((dacl->size + 3) & ~3);
517 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
527 /*******************************************************************
528 Duplicate a SEC_DESC structure.
529 ********************************************************************/
531 SEC_DESC *dup_sec_desc( SEC_DESC *src)
538 return make_sec_desc( src->revision, src->type,
539 src->owner_sid, src->grp_sid, src->sacl,
543 /*******************************************************************
544 Deletes a SEC_DESC structure
545 ********************************************************************/
547 void free_sec_desc(SEC_DESC **ppsd)
551 if(ppsd == NULL || *ppsd == NULL)
556 free_sec_acl(&psd->dacl);
557 free_sec_acl(&psd->dacl);
558 free(psd->owner_sid);
564 /*******************************************************************
565 Creates a SEC_DESC structure with typical defaults.
566 ********************************************************************/
568 SEC_DESC *make_standard_sec_desc(DOM_SID *owner_sid, DOM_SID *grp_sid,
569 SEC_ACL *dacl, size_t *sd_size)
571 return make_sec_desc(SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE|SEC_DESC_DACL_PRESENT,
572 owner_sid, grp_sid, NULL, dacl, sd_size);
575 /*******************************************************************
576 Reads or writes a SEC_DESC structure.
577 If reading and the *ppsd = NULL, allocates the structure.
578 ********************************************************************/
580 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
583 uint32 max_offset = 0; /* after we're done, move offset to end */
592 if(UNMARSHALLING(ps)) {
593 if((psd = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
598 /* Marshalling - just ignore. */
603 prs_debug(ps, depth, desc, "sec_io_desc");
609 /* start of security descriptor stored for back-calc offset purposes */
610 old_offset = prs_offset(ps);
612 if(!prs_uint16("revision ", ps, depth, &psd->revision))
615 if(!prs_uint16("type ", ps, depth, &psd->type))
618 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
621 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
624 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
627 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
630 max_offset = MAX(max_offset, prs_offset(ps));
632 if (psd->off_owner_sid != 0) {
634 if (UNMARSHALLING(ps)) {
635 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
638 if((psd->owner_sid = malloc(sizeof(*psd->owner_sid))) == NULL)
640 ZERO_STRUCTP(psd->owner_sid);
643 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
649 max_offset = MAX(max_offset, prs_offset(ps));
651 if (psd->off_grp_sid != 0) {
653 if (UNMARSHALLING(ps)) {
655 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
657 if((psd->grp_sid = malloc(sizeof(*psd->grp_sid))) == NULL)
659 ZERO_STRUCTP(psd->grp_sid);
662 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
668 max_offset = MAX(max_offset, prs_offset(ps));
670 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
671 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
673 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
679 max_offset = MAX(max_offset, prs_offset(ps));
681 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
682 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
684 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
690 max_offset = MAX(max_offset, prs_offset(ps));
692 if(!prs_set_offset(ps, max_offset))
697 /*******************************************************************
698 Creates a SEC_DESC_BUF structure.
699 ********************************************************************/
701 SEC_DESC_BUF *make_sec_desc_buf(size_t len, SEC_DESC *sec_desc)
705 if((dst = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
710 /* max buffer size (allocated size) */
711 dst->max_len = (uint32)len;
712 dst->len = (uint32)len;
714 if(sec_desc && ((dst->sec = dup_sec_desc(sec_desc)) == NULL)) {
715 free_sec_desc_buf(&dst);
722 /*******************************************************************
723 Duplicates a SEC_DESC_BUF structure.
724 ********************************************************************/
726 SEC_DESC_BUF *dup_sec_desc_buf(SEC_DESC_BUF *src)
731 return make_sec_desc_buf( src->len, src->sec);
734 /*******************************************************************
735 Deletes a SEC_DESC_BUF structure.
736 ********************************************************************/
738 void free_sec_desc_buf(SEC_DESC_BUF **ppsdb)
742 if(ppsdb == NULL || *ppsdb == NULL)
746 free_sec_desc(&psdb->sec);
752 /*******************************************************************
753 Reads or writes a SEC_DESC_BUF structure.
754 ********************************************************************/
756 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
769 if (UNMARSHALLING(ps) && psdb == NULL) {
770 if((psdb = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
776 prs_debug(ps, depth, desc, "sec_io_desc_buf");
782 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
785 if(!prs_uint32 ("undoc ", ps, depth, &psdb->undoc))
788 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
791 old_offset = prs_offset(ps);
793 /* reading, length is non-zero; writing, descriptor is non-NULL */
794 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
795 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
802 size = prs_offset(ps) - old_offset;
803 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
806 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))