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;
424 /* Create new security descriptor from bits */
426 psd = make_sec_desc(new_sdb->sec->revision,
427 owner_sid, group_sid, sacl, dacl, &secdesc_size);
429 return_sdb = make_sec_desc_buf(secdesc_size, psd);
436 /*******************************************************************
437 Creates a SEC_DESC structure
438 ********************************************************************/
440 SEC_DESC *make_sec_desc(uint16 revision,
441 DOM_SID *owner_sid, DOM_SID *grp_sid,
442 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
449 if(( dst = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
454 dst->revision = revision;
455 dst->type = SEC_DESC_SELF_RELATIVE;
457 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
458 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
460 dst->off_owner_sid = 0;
461 dst->off_grp_sid = 0;
465 if(owner_sid && ((dst->owner_sid = sid_dup(owner_sid)) == NULL))
468 if(grp_sid && ((dst->grp_sid = sid_dup(grp_sid)) == NULL))
471 if(sacl && ((dst->sacl = dup_sec_acl(sacl)) == NULL))
474 if(dacl && ((dst->dacl = dup_sec_acl(dacl)) == NULL))
480 * Work out the linearization sizes.
483 if (dst->owner_sid != NULL) {
486 offset = SD_HEADER_SIZE;
488 dst->off_owner_sid = offset;
489 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
492 if (dst->grp_sid != NULL) {
495 offset = SD_HEADER_SIZE;
497 dst->off_grp_sid = offset;
498 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
501 if (dst->sacl != NULL) {
504 offset = SD_HEADER_SIZE;
506 dst->off_sacl = offset;
507 offset += ((sacl->size + 3) & ~3);
510 if (dst->dacl != NULL) {
513 offset = SD_HEADER_SIZE;
515 dst->off_dacl = offset;
516 offset += ((dacl->size + 3) & ~3);
519 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
529 /*******************************************************************
530 Duplicate a SEC_DESC structure.
531 ********************************************************************/
533 SEC_DESC *dup_sec_desc( SEC_DESC *src)
540 return make_sec_desc( src->revision,
541 src->owner_sid, src->grp_sid, src->sacl,
545 /*******************************************************************
546 Deletes a SEC_DESC structure
547 ********************************************************************/
549 void free_sec_desc(SEC_DESC **ppsd)
553 if(ppsd == NULL || *ppsd == NULL)
558 free_sec_acl(&psd->dacl);
559 free_sec_acl(&psd->dacl);
560 free(psd->owner_sid);
566 /*******************************************************************
567 Creates a SEC_DESC structure with typical defaults.
568 ********************************************************************/
570 SEC_DESC *make_standard_sec_desc(DOM_SID *owner_sid, DOM_SID *grp_sid,
571 SEC_ACL *dacl, size_t *sd_size)
573 return make_sec_desc(SEC_DESC_REVISION,
574 owner_sid, grp_sid, NULL, dacl, sd_size);
577 /*******************************************************************
578 Reads or writes a SEC_DESC structure.
579 If reading and the *ppsd = NULL, allocates the structure.
580 ********************************************************************/
582 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
585 uint32 max_offset = 0; /* after we're done, move offset to end */
594 if(UNMARSHALLING(ps)) {
595 if((psd = (SEC_DESC *)malloc(sizeof(SEC_DESC))) == NULL)
600 /* Marshalling - just ignore. */
605 prs_debug(ps, depth, desc, "sec_io_desc");
611 /* start of security descriptor stored for back-calc offset purposes */
612 old_offset = prs_offset(ps);
614 if(!prs_uint16("revision ", ps, depth, &psd->revision))
617 if(!prs_uint16("type ", ps, depth, &psd->type))
620 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
623 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
626 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
629 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
632 max_offset = MAX(max_offset, prs_offset(ps));
634 if (psd->off_owner_sid != 0) {
636 if (UNMARSHALLING(ps)) {
637 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
640 if((psd->owner_sid = malloc(sizeof(*psd->owner_sid))) == NULL)
642 ZERO_STRUCTP(psd->owner_sid);
645 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
651 max_offset = MAX(max_offset, prs_offset(ps));
653 if (psd->off_grp_sid != 0) {
655 if (UNMARSHALLING(ps)) {
657 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
659 if((psd->grp_sid = malloc(sizeof(*psd->grp_sid))) == NULL)
661 ZERO_STRUCTP(psd->grp_sid);
664 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
670 max_offset = MAX(max_offset, prs_offset(ps));
672 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
673 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
675 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
681 max_offset = MAX(max_offset, prs_offset(ps));
683 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
684 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
686 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
692 max_offset = MAX(max_offset, prs_offset(ps));
694 if(!prs_set_offset(ps, max_offset))
699 /*******************************************************************
700 Creates a SEC_DESC_BUF structure.
701 ********************************************************************/
703 SEC_DESC_BUF *make_sec_desc_buf(size_t len, SEC_DESC *sec_desc)
707 if((dst = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
712 /* max buffer size (allocated size) */
713 dst->max_len = (uint32)len;
714 dst->len = (uint32)len;
716 if(sec_desc && ((dst->sec = dup_sec_desc(sec_desc)) == NULL)) {
717 free_sec_desc_buf(&dst);
724 /*******************************************************************
725 Duplicates a SEC_DESC_BUF structure.
726 ********************************************************************/
728 SEC_DESC_BUF *dup_sec_desc_buf(SEC_DESC_BUF *src)
733 return make_sec_desc_buf( src->len, src->sec);
736 /*******************************************************************
737 Deletes a SEC_DESC_BUF structure.
738 ********************************************************************/
740 void free_sec_desc_buf(SEC_DESC_BUF **ppsdb)
744 if(ppsdb == NULL || *ppsdb == NULL)
748 free_sec_desc(&psdb->sec);
754 /*******************************************************************
755 Reads or writes a SEC_DESC_BUF structure.
756 ********************************************************************/
758 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
771 if (UNMARSHALLING(ps) && psdb == NULL) {
772 if((psdb = (SEC_DESC_BUF *)malloc(sizeof(SEC_DESC_BUF))) == NULL)
778 prs_debug(ps, depth, desc, "sec_io_desc_buf");
784 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
787 if(!prs_uint32 ("undoc ", ps, depth, &psdb->undoc))
790 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
793 old_offset = prs_offset(ps);
795 /* reading, length is non-zero; writing, descriptor is non-NULL */
796 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
797 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
804 size = prs_offset(ps) - old_offset;
805 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
808 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))