At the prompting, start to add infrastructure to detect the presence of
[Samba/gebeck_regimport.git] / source3 / rpc_parse / parse_sec.c
bloba49a34139e0bce9a00209de05b68aaa8461246ac
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
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.
9 *
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.
25 #include "includes.h"
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_PARSE
30 /*******************************************************************
31 Sets up a SEC_ACCESS structure.
32 ********************************************************************/
34 void init_sec_access(SEC_ACCESS *t, uint32 mask)
36 t->mask = mask;
39 /*******************************************************************
40 Reads or writes a SEC_ACCESS structure.
41 ********************************************************************/
43 BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
45 if (t == NULL)
46 return False;
48 prs_debug(ps, depth, desc, "sec_io_access");
49 depth++;
51 if(!prs_uint32("mask", ps, depth, &(t->mask)))
52 return False;
54 return True;
57 /*******************************************************************
58 Check if ACE has OBJECT type.
59 ********************************************************************/
61 BOOL sec_ace_object(uint8 type)
63 if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
64 type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
65 type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
66 type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
67 return True;
69 return False;
72 /*******************************************************************
73 copy a SEC_ACE structure.
74 ********************************************************************/
75 void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
77 ace_dest->type = ace_src->type;
78 ace_dest->flags = ace_src->flags;
79 ace_dest->size = ace_src->size;
80 ace_dest->info.mask = ace_src->info.mask;
81 ace_dest->obj_flags = ace_src->obj_flags;
82 memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE);
83 memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE);
84 sid_copy(&ace_dest->trustee, &ace_src->trustee);
87 /*******************************************************************
88 Sets up a SEC_ACE structure.
89 ********************************************************************/
91 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
93 t->type = type;
94 t->flags = flag;
95 t->size = sid_size(sid) + 8;
96 t->info = mask;
98 ZERO_STRUCTP(&t->trustee);
99 sid_copy(&t->trustee, sid);
102 /*******************************************************************
103 Reads or writes a SEC_ACE structure.
104 ********************************************************************/
106 BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
108 uint32 old_offset;
109 uint32 offset_ace_size;
111 if (psa == NULL)
112 return False;
114 prs_debug(ps, depth, desc, "sec_io_ace");
115 depth++;
117 old_offset = prs_offset(ps);
119 if(!prs_uint8("type ", ps, depth, &psa->type))
120 return False;
122 if(!prs_uint8("flags", ps, depth, &psa->flags))
123 return False;
125 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
126 return False;
128 if(!sec_io_access("info ", &psa->info, ps, depth))
129 return False;
131 /* check whether object access is present */
132 if (!sec_ace_object(psa->type)) {
133 if (!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth))
134 return False;
135 } else {
136 if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
137 return False;
139 if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
140 if (!prs_uint8s(False, "obj_guid", ps, depth, psa->obj_guid.info, GUID_SIZE))
141 return False;
143 if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
144 if (!prs_uint8s(False, "inh_guid", ps, depth, psa->inh_guid.info, GUID_SIZE))
145 return False;
147 if(!smb_io_dom_sid("trustee ", &psa->trustee , ps, depth))
148 return False;
151 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
152 return False;
153 return True;
156 /*******************************************************************
157 adds new SID with its permissions to ACE list
158 ********************************************************************/
160 NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask)
162 int i = 0;
164 if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER;
166 *num += 1;
168 if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0)
169 return NT_STATUS_NO_MEMORY;
171 for (i = 0; i < *num - 1; i ++)
172 sec_ace_copy(&(*new)[i], &old[i]);
174 (*new)[i].type = 0;
175 (*new)[i].flags = 0;
176 (*new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid);
177 (*new)[i].info.mask = mask;
178 sid_copy(&(*new)[i].trustee, sid);
179 return NT_STATUS_OK;
182 /*******************************************************************
183 modify SID's permissions at ACL
184 ********************************************************************/
186 NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
188 int i = 0;
190 if (!ace || !sid) return NT_STATUS_INVALID_PARAMETER;
192 for (i = 0; i < num; i ++) {
193 if (sid_compare(&ace[i].trustee, sid) == 0) {
194 ace[i].info.mask = mask;
195 return NT_STATUS_OK;
198 return NT_STATUS_NOT_FOUND;
201 /*******************************************************************
202 delete SID from ACL
203 ********************************************************************/
205 NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, size_t *num, DOM_SID *sid)
207 int i = 0;
208 int n_del = 0;
210 if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER;
212 if((new[0] = (SEC_ACE *) talloc_zero(ctx, *num * sizeof(SEC_ACE))) == 0)
213 return NT_STATUS_NO_MEMORY;
215 for (i = 0; i < *num; i ++) {
216 if (sid_compare(&old[i].trustee, sid) != 0)
217 sec_ace_copy(&(*new)[i], &old[i]);
218 else
219 n_del ++;
221 if (n_del == 0)
222 return NT_STATUS_NOT_FOUND;
223 else {
224 *num -= n_del;
225 return NT_STATUS_OK;
229 /*******************************************************************
230 Create a SEC_ACL structure.
231 ********************************************************************/
233 SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
235 SEC_ACL *dst;
236 int i;
238 if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
239 return NULL;
241 dst->revision = revision;
242 dst->num_aces = num_aces;
243 dst->size = SEC_ACL_HEADER_SIZE;
245 /* Now we need to return a non-NULL address for the ace list even
246 if the number of aces required is zero. This is because there
247 is a distinct difference between a NULL ace and an ace with zero
248 entries in it. This is achieved by checking that num_aces is a
249 positive number. */
251 if ((num_aces) &&
252 ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces))
253 == NULL)) {
254 return NULL;
257 for (i = 0; i < num_aces; i++) {
258 dst->ace[i] = ace_list[i]; /* Structure copy. */
259 dst->size += ace_list[i].size;
262 return dst;
265 /*******************************************************************
266 Duplicate a SEC_ACL structure.
267 ********************************************************************/
269 SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
271 if(src == NULL)
272 return NULL;
274 return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
277 /*******************************************************************
278 Reads or writes a SEC_ACL structure.
280 First of the xx_io_xx functions that allocates its data structures
281 for you as it reads them.
282 ********************************************************************/
284 BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
286 int i;
287 uint32 old_offset;
288 uint32 offset_acl_size;
289 SEC_ACL *psa;
292 * Note that the size is always a multiple of 4 bytes due to the
293 * nature of the data structure. Therefore the prs_align() calls
294 * have been removed as they through us off when doing two-layer
295 * marshalling such as in the printing code (NEW_BUFFER). --jerry
298 if (ppsa == NULL)
299 return False;
301 psa = *ppsa;
303 if(UNMARSHALLING(ps) && psa == NULL) {
305 * This is a read and we must allocate the stuct to read into.
307 if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
308 return False;
309 *ppsa = psa;
312 prs_debug(ps, depth, desc, "sec_io_acl");
313 depth++;
315 old_offset = prs_offset(ps);
317 if(!prs_uint16("revision", ps, depth, &psa->revision))
318 return False;
320 if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_acl_size))
321 return False;
323 if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
324 return False;
326 if (UNMARSHALLING(ps)) {
328 * Even if the num_aces is zero, allocate memory as there's a difference
329 * between a non-present DACL (allow all access) and a DACL with no ACE's
330 * (allow no access).
332 if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
333 return False;
336 for (i = 0; i < psa->num_aces; i++) {
337 fstring tmp;
338 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
339 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
340 return False;
343 if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_acl_size, old_offset))
344 return False;
346 return True;
349 /*******************************************************************
350 Works out the linearization size of a SEC_DESC.
351 ********************************************************************/
353 size_t sec_desc_size(SEC_DESC *psd)
355 size_t offset;
357 if (!psd) return 0;
359 offset = SEC_DESC_HEADER_SIZE;
361 /* don't align */
363 if (psd->owner_sid != NULL)
364 offset += sid_size(psd->owner_sid);
366 if (psd->grp_sid != NULL)
367 offset += sid_size(psd->grp_sid);
369 if (psd->sacl != NULL)
370 offset += psd->sacl->size;
372 if (psd->dacl != NULL)
373 offset += psd->dacl->size;
375 return offset;
378 /*******************************************************************
379 Compares two SEC_ACE structures
380 ********************************************************************/
382 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
384 /* Trivial case */
386 if (!s1 && !s2) return True;
388 /* Check top level stuff */
390 if (s1->type != s2->type || s1->flags != s2->flags ||
391 s1->info.mask != s2->info.mask) {
392 return False;
395 /* Check SID */
397 if (!sid_equal(&s1->trustee, &s2->trustee)) {
398 return False;
401 return True;
404 /*******************************************************************
405 Compares two SEC_ACL structures
406 ********************************************************************/
408 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
410 int i, j;
412 /* Trivial cases */
414 if (!s1 && !s2) return True;
415 if (!s1 || !s2) return False;
417 /* Check top level stuff */
419 if (s1->revision != s2->revision) {
420 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
421 s1->revision, s2->revision));
422 return False;
425 if (s1->num_aces != s2->num_aces) {
426 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
427 s1->revision, s2->revision));
428 return False;
431 /* The ACEs could be in any order so check each ACE in s1 against
432 each ACE in s2. */
434 for (i = 0; i < s1->num_aces; i++) {
435 BOOL found = False;
437 for (j = 0; j < s2->num_aces; j++) {
438 if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
439 found = True;
440 break;
444 if (!found) return False;
447 return True;
450 /*******************************************************************
451 Compares two SEC_DESC structures
452 ********************************************************************/
454 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
456 /* Trivial case */
458 if (!s1 && !s2) {
459 goto done;
462 /* Check top level stuff */
464 if (s1->revision != s2->revision) {
465 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
466 s1->revision, s2->revision));
467 return False;
470 if (s1->type!= s2->type) {
471 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
472 s1->type, s2->type));
473 return False;
476 /* Check owner and group */
478 if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
479 fstring str1, str2;
481 sid_to_string(str1, s1->owner_sid);
482 sid_to_string(str2, s2->owner_sid);
484 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
485 str1, str2));
486 return False;
489 if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
490 fstring str1, str2;
492 sid_to_string(str1, s1->grp_sid);
493 sid_to_string(str2, s2->grp_sid);
495 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
496 str1, str2));
497 return False;
500 /* Check ACLs present in one but not the other */
502 if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
503 (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
504 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
505 return False;
508 /* Sigh - we have to do it the hard way by iterating over all
509 the ACEs in the ACLs */
511 if (!sec_acl_equal(s1->dacl, s2->dacl) ||
512 !sec_acl_equal(s1->sacl, s2->sacl)) {
513 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
514 return False;
517 done:
518 DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
519 return True;
522 /*******************************************************************
523 Merge part of security descriptor old_sec in to the empty sections of
524 security descriptor new_sec.
525 ********************************************************************/
527 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
529 DOM_SID *owner_sid, *group_sid;
530 SEC_DESC_BUF *return_sdb;
531 SEC_ACL *dacl, *sacl;
532 SEC_DESC *psd = NULL;
533 uint16 secdesc_type;
534 size_t secdesc_size;
536 /* Copy over owner and group sids. There seems to be no flag for
537 this so just check the pointer values. */
539 owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
540 old_sdb->sec->owner_sid;
542 group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
543 old_sdb->sec->grp_sid;
545 secdesc_type = new_sdb->sec->type;
547 /* Ignore changes to the system ACL. This has the effect of making
548 changes through the security tab audit button not sticking.
549 Perhaps in future Samba could implement these settings somehow. */
551 sacl = NULL;
552 secdesc_type &= ~SEC_DESC_SACL_PRESENT;
554 /* Copy across discretionary ACL */
556 if (secdesc_type & SEC_DESC_DACL_PRESENT) {
557 dacl = new_sdb->sec->dacl;
558 } else {
559 dacl = old_sdb->sec->dacl;
562 /* Create new security descriptor from bits */
564 psd = make_sec_desc(ctx, new_sdb->sec->revision,
565 owner_sid, group_sid, sacl, dacl, &secdesc_size);
567 return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
569 return(return_sdb);
572 /*******************************************************************
573 Tallocs a duplicate SID.
574 ********************************************************************/
576 static DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src)
578 DOM_SID *dst;
580 if(!src)
581 return NULL;
583 if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) {
584 sid_copy( dst, src);
587 return dst;
590 /*******************************************************************
591 Creates a SEC_DESC structure
592 ********************************************************************/
594 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision,
595 DOM_SID *owner_sid, DOM_SID *grp_sid,
596 SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
598 SEC_DESC *dst;
599 uint32 offset = 0;
600 uint32 offset_sid = SEC_DESC_HEADER_SIZE;
601 uint32 offset_acl = 0;
603 *sd_size = 0;
605 if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
606 return NULL;
608 dst->revision = revision;
609 dst->type = SEC_DESC_SELF_RELATIVE;
611 if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
612 if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
614 dst->off_owner_sid = 0;
615 dst->off_grp_sid = 0;
616 dst->off_sacl = 0;
617 dst->off_dacl = 0;
619 if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
620 goto error_exit;
622 if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
623 goto error_exit;
625 if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
626 goto error_exit;
628 if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
629 goto error_exit;
631 offset = 0;
634 * Work out the linearization sizes.
636 if (dst->owner_sid != NULL) {
638 if (offset == 0)
639 offset = SEC_DESC_HEADER_SIZE;
641 offset += sid_size(dst->owner_sid);
644 if (dst->grp_sid != NULL) {
646 if (offset == 0)
647 offset = SEC_DESC_HEADER_SIZE;
649 offset += sid_size(dst->grp_sid);
652 if (dst->sacl != NULL) {
654 offset_acl = SEC_DESC_HEADER_SIZE;
656 dst->off_sacl = offset_acl;
657 offset_acl += dst->sacl->size;
658 offset += dst->sacl->size;
659 offset_sid += dst->sacl->size;
662 if (dst->dacl != NULL) {
664 if (offset_acl == 0)
665 offset_acl = SEC_DESC_HEADER_SIZE;
667 dst->off_dacl = offset_acl;
668 offset_acl += dst->dacl->size;
669 offset += dst->dacl->size;
670 offset_sid += dst->dacl->size;
673 *sd_size = (size_t)((offset == 0) ? SEC_DESC_HEADER_SIZE : offset);
675 if (dst->owner_sid != NULL)
676 dst->off_owner_sid = offset_sid;
678 /* sid_size() returns 0 if the sid is NULL so this is ok */
680 if (dst->grp_sid != NULL)
681 dst->off_grp_sid = offset_sid + sid_size(dst->owner_sid);
683 return dst;
685 error_exit:
687 *sd_size = 0;
688 return NULL;
691 /*******************************************************************
692 Duplicate a SEC_DESC structure.
693 ********************************************************************/
695 SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src)
697 size_t dummy;
699 if(src == NULL)
700 return NULL;
702 return make_sec_desc( ctx, src->revision,
703 src->owner_sid, src->grp_sid, src->sacl,
704 src->dacl, &dummy);
707 /*******************************************************************
708 Creates a SEC_DESC structure with typical defaults.
709 ********************************************************************/
711 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
712 SEC_ACL *dacl, size_t *sd_size)
714 return make_sec_desc(ctx, SEC_DESC_REVISION,
715 owner_sid, grp_sid, NULL, dacl, sd_size);
718 /*******************************************************************
719 Reads or writes a SEC_DESC structure.
720 If reading and the *ppsd = NULL, allocates the structure.
721 ********************************************************************/
723 BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
725 uint32 old_offset;
726 uint32 max_offset = 0; /* after we're done, move offset to end */
727 uint32 tmp_offset = 0;
729 SEC_DESC *psd;
731 if (ppsd == NULL)
732 return False;
734 psd = *ppsd;
736 if (psd == NULL) {
737 if(UNMARSHALLING(ps)) {
738 if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
739 return False;
740 *ppsd = psd;
741 } else {
742 /* Marshalling - just ignore. */
743 return True;
747 prs_debug(ps, depth, desc, "sec_io_desc");
748 depth++;
750 #if 0
752 * if alignment is needed, should be done by the the
753 * caller. Not here. This caused me problems when marshalling
754 * printer info into a buffer. --jerry
756 if(!prs_align(ps))
757 return False;
758 #endif
760 /* start of security descriptor stored for back-calc offset purposes */
761 old_offset = prs_offset(ps);
763 if(!prs_uint16("revision ", ps, depth, &psd->revision))
764 return False;
766 if(!prs_uint16("type ", ps, depth, &psd->type))
767 return False;
769 if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
770 return False;
772 if(!prs_uint32("off_grp_sid ", ps, depth, &psd->off_grp_sid))
773 return False;
775 if(!prs_uint32("off_sacl ", ps, depth, &psd->off_sacl))
776 return False;
778 if(!prs_uint32("off_dacl ", ps, depth, &psd->off_dacl))
779 return False;
781 max_offset = MAX(max_offset, prs_offset(ps));
783 if (psd->off_owner_sid != 0) {
785 tmp_offset = ps->data_offset;
786 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
787 return False;
789 if (UNMARSHALLING(ps)) {
790 /* reading */
791 if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
792 return False;
795 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
796 return False;
798 max_offset = MAX(max_offset, prs_offset(ps));
800 if (!prs_set_offset(ps,tmp_offset))
801 return False;
804 if (psd->off_grp_sid != 0) {
806 tmp_offset = ps->data_offset;
807 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
808 return False;
810 if (UNMARSHALLING(ps)) {
811 /* reading */
812 if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
813 return False;
816 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
817 return False;
819 max_offset = MAX(max_offset, prs_offset(ps));
821 if (!prs_set_offset(ps,tmp_offset))
822 return False;
825 if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
826 tmp_offset = ps->data_offset;
827 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
828 return False;
829 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
830 return False;
831 max_offset = MAX(max_offset, prs_offset(ps));
832 if (!prs_set_offset(ps,tmp_offset))
833 return False;
837 if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
838 tmp_offset = ps->data_offset;
839 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
840 return False;
841 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
842 return False;
843 max_offset = MAX(max_offset, prs_offset(ps));
844 if (!prs_set_offset(ps,tmp_offset))
845 return False;
848 if(!prs_set_offset(ps, max_offset))
849 return False;
850 return True;
853 /*******************************************************************
854 Creates a SEC_DESC_BUF structure.
855 ********************************************************************/
857 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
859 SEC_DESC_BUF *dst;
861 if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
862 return NULL;
864 /* max buffer size (allocated size) */
865 dst->max_len = (uint32)len;
866 dst->len = (uint32)len;
868 if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
869 return NULL;
872 dst->ptr = 0x1;
874 return dst;
877 /*******************************************************************
878 Duplicates a SEC_DESC_BUF structure.
879 ********************************************************************/
881 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
883 if(src == NULL)
884 return NULL;
886 return make_sec_desc_buf( ctx, src->len, src->sec);
889 /*******************************************************************
890 Reads or writes a SEC_DESC_BUF structure.
891 ********************************************************************/
893 BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
895 uint32 off_len;
896 uint32 off_max_len;
897 uint32 old_offset;
898 uint32 size;
899 SEC_DESC_BUF *psdb;
901 if (ppsdb == NULL)
902 return False;
904 psdb = *ppsdb;
906 if (UNMARSHALLING(ps) && psdb == NULL) {
907 if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
908 return False;
909 *ppsdb = psdb;
912 prs_debug(ps, depth, desc, "sec_io_desc_buf");
913 depth++;
915 if(!prs_align(ps))
916 return False;
918 if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
919 return False;
921 if(!prs_uint32 ("ptr ", ps, depth, &psdb->ptr))
922 return False;
924 if(!prs_uint32_pre("len ", ps, depth, &psdb->len, &off_len))
925 return False;
927 old_offset = prs_offset(ps);
929 /* reading, length is non-zero; writing, descriptor is non-NULL */
930 if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
931 if(!sec_io_desc("sec ", &psdb->sec, ps, depth))
932 return False;
935 if(!prs_align(ps))
936 return False;
938 size = prs_offset(ps) - old_offset;
939 if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
940 return False;
942 if(!prs_uint32_post("len ", ps, depth, &psdb->len, off_len, size))
943 return False;
945 return True;
948 /*******************************************************************
949 adds new SID with its permissions to SEC_DESC
950 ********************************************************************/
952 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
954 SEC_DESC *sd = 0;
955 SEC_ACL *dacl = 0;
956 SEC_ACE *ace = 0;
957 NTSTATUS status;
959 *sd_size = 0;
961 if (!ctx || !psd || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
963 status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
965 if (!NT_STATUS_IS_OK(status))
966 return status;
968 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
969 return NT_STATUS_UNSUCCESSFUL;
971 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->owner_sid,
972 psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
973 return NT_STATUS_UNSUCCESSFUL;
975 *psd = sd;
976 sd = 0;
977 return NT_STATUS_OK;
980 /*******************************************************************
981 modify SID's permissions at SEC_DESC
982 ********************************************************************/
984 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
986 NTSTATUS status;
988 if (!sd || !sid) return NT_STATUS_INVALID_PARAMETER;
990 status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
992 if (!NT_STATUS_IS_OK(status))
993 return status;
995 return NT_STATUS_OK;
998 /*******************************************************************
999 delete SID from SEC_DESC
1000 ********************************************************************/
1002 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
1004 SEC_DESC *sd = 0;
1005 SEC_ACL *dacl = 0;
1006 SEC_ACE *ace = 0;
1007 NTSTATUS status;
1009 *sd_size = 0;
1011 if (!ctx || !psd[0] || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
1013 status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
1015 if (!NT_STATUS_IS_OK(status))
1016 return status;
1018 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
1019 return NT_STATUS_UNSUCCESSFUL;
1021 if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->owner_sid,
1022 psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
1023 return NT_STATUS_UNSUCCESSFUL;
1025 *psd = sd;
1026 sd = 0;
1027 return NT_STATUS_OK;