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.
27 extern int DEBUGLEVEL;
29 #define SD_HEADER_SIZE 0x14
31 /*******************************************************************
32 Sets up a SEC_ACCESS structure.
33 ********************************************************************/
35 void init_sec_access(SEC_ACCESS *t, uint32 mask)
40 /*******************************************************************
41 Reads or writes a SEC_ACCESS structure.
42 ********************************************************************/
44 BOOL sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
49 prs_debug(ps, depth, desc, "sec_io_access");
55 if(!prs_uint32("mask", ps, depth, &(t->mask)))
62 /*******************************************************************
63 Sets up a SEC_ACE structure.
64 ********************************************************************/
66 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
70 t->size = sid_size(sid) + 8;
73 ZERO_STRUCTP(&t->sid);
74 sid_copy(&t->sid, sid);
77 /*******************************************************************
78 Reads or writes a SEC_ACE structure.
79 ********************************************************************/
81 BOOL sec_io_ace(char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
84 uint32 offset_ace_size;
89 prs_debug(ps, depth, desc, "sec_io_ace");
95 old_offset = prs_offset(ps);
97 if(!prs_uint8("type ", ps, depth, &psa->type))
100 if(!prs_uint8("flags", ps, depth, &psa->flags))
103 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
106 if(!sec_io_access("info ", &psa->info, ps, depth))
112 if(!smb_io_dom_sid("sid ", &psa->sid , ps, depth))
115 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
121 /*******************************************************************
122 Create a SEC_ACL structure.
123 ********************************************************************/
125 SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
130 if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
133 dst->revision = revision;
134 dst->num_aces = num_aces;
137 /* Now we need to return a non-NULL address for the ace list even
138 if the number of aces required is zero. This is because there
139 is a distinct difference between a NULL ace and an ace with zero
140 entries in it. This is achieved by checking that num_aces is a
144 ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces))
149 for (i = 0; i < num_aces; i++) {
150 dst->ace[i] = ace_list[i]; /* Structure copy. */
151 dst->size += ace_list[i].size;
157 /*******************************************************************
158 Duplicate a SEC_ACL structure.
159 ********************************************************************/
161 SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
166 return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
169 /*******************************************************************
170 Reads or writes a SEC_ACL structure.
172 First of the xx_io_xx functions that allocates its data structures
173 for you as it reads them.
174 ********************************************************************/
176 BOOL sec_io_acl(char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
180 uint32 offset_acl_size;
188 if(UNMARSHALLING(ps) && psa == NULL) {
190 * This is a read and we must allocate the stuct to read into.
192 if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
197 prs_debug(ps, depth, desc, "sec_io_acl");
203 old_offset = prs_offset(ps);
205 if(!prs_uint16("revision", ps, depth, &psa->revision))
208 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size))
211 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
214 if (UNMARSHALLING(ps)) {
216 * Even if the num_aces is zero, allocate memory as there's a difference
217 * between a non-present DACL (allow all access) and a DACL with no ACE's
220 if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
224 for (i = 0; i < psa->num_aces; i++) {
226 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
227 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
234 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset))
240 /*******************************************************************
241 Works out the linearization size of a SEC_DESC.
242 ********************************************************************/
244 size_t sec_desc_size(SEC_DESC *psd)
250 offset = SD_HEADER_SIZE;
252 if (psd->owner_sid != NULL)
253 offset += ((sid_size(psd->owner_sid) + 3) & ~3);
255 if (psd->grp_sid != NULL)
256 offset += ((sid_size(psd->grp_sid) + 3) & ~3);
258 if (psd->sacl != NULL)
259 offset += ((psd->sacl->size + 3) & ~3);
261 if (psd->dacl != NULL)
262 offset += ((psd->dacl->size + 3) & ~3);
267 /*******************************************************************
268 Compares two SEC_ACE structures
269 ********************************************************************/
271 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
275 if (!s1 && !s2) return True;
277 /* Check top level stuff */
279 if (s1->type != s2->type || s1->flags != s2->flags ||
280 s1->info.mask != s2->info.mask) {
286 if (!sid_equal(&s1->sid, &s2->sid)) {
293 /*******************************************************************
294 Compares two SEC_ACL structures
295 ********************************************************************/
297 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
303 if (!s1 && !s2) return True;
304 if (!s1 || !s2) return False;
306 /* Check top level stuff */
308 if (s1->revision != s2->revision) {
309 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
310 s1->revision, s2->revision));
314 if (s1->num_aces != s2->num_aces) {
315 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
316 s1->revision, s2->revision));
320 /* The ACEs could be in any order so check each ACE in s1 against
323 for (i = 0; i < s1->num_aces; i++) {
326 for (j = 0; j < s2->num_aces; j++) {
327 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
333 if (!found) return False;
339 /*******************************************************************
340 Compares two SEC_DESC structures
341 ********************************************************************/
343 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
351 /* Check top level stuff */
353 if (s1->revision != s2->revision) {
354 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
355 s1->revision, s2->revision));
359 if (s1->type!= s2->type) {
360 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
361 s1->type, s2->type));
365 /* Check owner and group */
367 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
370 sid_to_string(str1, s1->owner_sid);
371 sid_to_string(str2, s2->owner_sid);
373 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
378 if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
381 sid_to_string(str1, s1->grp_sid);
382 sid_to_string(str2, s2->grp_sid);
384 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
389 /* Check ACLs present in one but not the other */
391 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
392 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
393 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
397 /* Sigh - we have to do it the hard way by iterating over all
398 the ACEs in the ACLs */
400 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
401 !sec_acl_equal(s1->sacl, s2->sacl)) {
402 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
407 DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
411 /*******************************************************************
412 Merge part of security descriptor old_sec in to the empty sections of
413 security descriptor new_sec.
414 ********************************************************************/
416 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
418 DOM_SID *owner_sid, *group_sid;
419 SEC_DESC_BUF *return_sdb;
420 SEC_ACL *dacl, *sacl;
421 SEC_DESC *psd = NULL;
425 /* Copy over owner and group sids. There seems to be no flag for
426 this so just check the pointer values. */
428 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
429 old_sdb->sec->owner_sid;
431 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
432 old_sdb->sec->grp_sid;
434 secdesc_type = new_sdb->sec->type;
436 /* Ignore changes to the system ACL. This has the effect of making
437 changes through the security tab audit button not sticking.
438 Perhaps in future Samba could implement these settings somehow. */
441 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
443 /* Copy across discretionary ACL */
445 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
446 dacl = new_sdb->sec->dacl;
448 dacl = old_sdb->sec->dacl;
451 /* Create new security descriptor from bits */
453 psd = make_sec_desc(ctx, new_sdb->sec->revision,
454 owner_sid, group_sid, sacl, dacl, &secdesc_size);
456 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
461 /*******************************************************************
462 Tallocs a duplicate SID.
463 ********************************************************************/
465 static DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src)
472 if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) {
479 /*******************************************************************
480 Creates a SEC_DESC structure
481 ********************************************************************/
483 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
484 DOM_SID *owner_sid, DOM_SID *grp_sid,
485 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
492 if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
495 dst->revision = revision;
496 dst->type = SEC_DESC_SELF_RELATIVE;
498 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
499 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
501 dst->off_owner_sid = 0;
502 dst->off_grp_sid = 0;
506 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
509 if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
512 if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
515 if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
521 * Work out the linearization sizes.
524 if (dst->owner_sid != NULL) {
527 offset = SD_HEADER_SIZE;
529 dst->off_owner_sid = offset;
530 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
533 if (dst->grp_sid != NULL) {
536 offset = SD_HEADER_SIZE;
538 dst->off_grp_sid = offset;
539 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
542 if (dst->sacl != NULL) {
545 offset = SD_HEADER_SIZE;
547 dst->off_sacl = offset;
548 offset += ((dst->sacl->size + 3) & ~3);
551 if (dst->dacl != NULL) {
554 offset = SD_HEADER_SIZE;
556 dst->off_dacl = offset;
557 offset += ((dst->dacl->size + 3) & ~3);
560 *sd_size = (size_t)((offset == 0) ? SD_HEADER_SIZE : offset);
569 /*******************************************************************
570 Duplicate a SEC_DESC structure.
571 ********************************************************************/
573 SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src)
580 return make_sec_desc( ctx, src->revision,
581 src->owner_sid, src->grp_sid, src->sacl,
585 /*******************************************************************
586 Creates a SEC_DESC structure with typical defaults.
587 ********************************************************************/
589 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
590 SEC_ACL *dacl, size_t *sd_size)
592 return make_sec_desc(ctx, SEC_DESC_REVISION,
593 owner_sid, grp_sid, NULL, dacl, sd_size);
596 /*******************************************************************
597 Reads or writes a SEC_DESC structure.
598 If reading and the *ppsd = NULL, allocates the structure.
599 ********************************************************************/
601 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
604 uint32 max_offset = 0; /* after we're done, move offset to end */
613 if(UNMARSHALLING(ps)) {
614 if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
618 /* Marshalling - just ignore. */
623 prs_debug(ps, depth, desc, "sec_io_desc");
629 /* start of security descriptor stored for back-calc offset purposes */
630 old_offset = prs_offset(ps);
632 if(!prs_uint16("revision ", ps, depth, &psd->revision))
635 if(!prs_uint16("type ", ps, depth, &psd->type))
638 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
641 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
644 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
647 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
650 max_offset = MAX(max_offset, prs_offset(ps));
652 if (psd->off_owner_sid != 0) {
654 if (UNMARSHALLING(ps)) {
655 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
658 if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
662 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
668 max_offset = MAX(max_offset, prs_offset(ps));
670 if (psd->off_grp_sid != 0) {
672 if (UNMARSHALLING(ps)) {
674 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
676 if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
680 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
686 max_offset = MAX(max_offset, prs_offset(ps));
688 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
689 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
691 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
697 max_offset = MAX(max_offset, prs_offset(ps));
699 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
700 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
702 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
708 max_offset = MAX(max_offset, prs_offset(ps));
710 if(!prs_set_offset(ps, max_offset))
715 /*******************************************************************
716 Creates a SEC_DESC_BUF structure.
717 ********************************************************************/
719 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
723 if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
726 /* max buffer size (allocated size) */
727 dst->max_len = (uint32)len;
728 dst->len = (uint32)len;
730 if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
739 /*******************************************************************
740 Duplicates a SEC_DESC_BUF structure.
741 ********************************************************************/
743 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
748 return make_sec_desc_buf( ctx, src->len, src->sec);
751 /*******************************************************************
752 Reads or writes a SEC_DESC_BUF structure.
753 ********************************************************************/
755 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
768 if (UNMARSHALLING(ps) && psdb == NULL) {
769 if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
774 prs_debug(ps, depth, desc, "sec_io_desc_buf");
780 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
783 if(!prs_uint32 ("ptr ", ps, depth, &psdb->ptr))
786 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
789 old_offset = prs_offset(ps);
791 /* reading, length is non-zero; writing, descriptor is non-NULL */
792 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
793 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
800 size = prs_offset(ps) - old_offset;
801 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
804 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))