more debug classess activated
[samba.git] / source / rpc_parse / parse_sec.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1998,
5  *  Copyright (C) Jeremy R. Allison            1995-1998
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
7  *  Copyright (C) Paul Ashton                  1997-1998.
8  *  
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *  
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *  
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_PARSE
28
29 /*******************************************************************
30  Sets up a SEC_ACCESS structure.
31 ********************************************************************/
32
33 void init_sec_access(SEC_ACCESS *t, uint32 mask)
34 {
35         t->mask = mask;
36 }
37
38 /*******************************************************************
39  Reads or writes a SEC_ACCESS structure.
40 ********************************************************************/
41
42 BOOL sec_io_access(char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
43 {
44         if (t == NULL)
45                 return False;
46
47         prs_debug(ps, depth, desc, "sec_io_access");
48         depth++;
49
50         if(!prs_align(ps))
51                 return False;
52         
53         if(!prs_uint32("mask", ps, depth, &(t->mask)))
54                 return False;
55
56         return True;
57 }
58
59 /*******************************************************************
60  Check if ACE has OBJECT type.
61 ********************************************************************/
62
63 BOOL sec_ace_object(uint8 type)
64 {
65         if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT ||
66             type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT ||
67             type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT ||
68             type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) {
69                 return True;
70         }
71         return False;
72 }
73
74 /*******************************************************************
75  copy a SEC_ACE structure.
76 ********************************************************************/
77 void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
78 {
79         ace_dest->type  = ace_src->type;
80         ace_dest->flags = ace_src->flags;
81         ace_dest->size  = ace_src->size;
82         ace_dest->info.mask = ace_src->info.mask;
83         ace_dest->obj_flags = ace_src->obj_flags;
84         memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE);
85         memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE);     
86         sid_copy(&ace_dest->trustee, &ace_src->trustee);
87 }
88
89 /*******************************************************************
90  Sets up a SEC_ACE structure.
91 ********************************************************************/
92
93 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
94 {
95         t->type = type;
96         t->flags = flag;
97         t->size = sid_size(sid) + 8;
98         t->info = mask;
99
100         ZERO_STRUCTP(&t->trustee);
101         sid_copy(&t->trustee, sid);
102 }
103
104 /*******************************************************************
105  Reads or writes a SEC_ACE structure.
106 ********************************************************************/
107
108 BOOL sec_io_ace(char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
109 {
110         uint32 old_offset;
111         uint32 offset_ace_size;
112
113         if (psa == NULL)
114                 return False;
115
116         prs_debug(ps, depth, desc, "sec_io_ace");
117         depth++;
118
119         if(!prs_align(ps))
120                 return False;
121         
122         old_offset = prs_offset(ps);
123
124         if(!prs_uint8("type ", ps, depth, &psa->type))
125                 return False;
126
127         if(!prs_uint8("flags", ps, depth, &psa->flags))
128                 return False;
129
130         if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
131                 return False;
132
133         if(!sec_io_access("info ", &psa->info, ps, depth))
134                 return False;
135
136         if(!prs_align(ps))
137                 return False;
138
139         /* check whether object access is present */
140         if (!sec_ace_object(psa->type)) {
141                 if (!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
142                         return False;
143         } else {
144                 if (!prs_uint32("obj_flags", ps, depth, &psa->obj_flags))
145                         return False;
146
147                 if (psa->obj_flags & SEC_ACE_OBJECT_PRESENT)
148                         if (!prs_uint8s(False, "obj_guid", ps, depth, psa->obj_guid.info, GUID_SIZE))
149                                 return False;
150
151                 if (psa->obj_flags & SEC_ACE_OBJECT_INHERITED_PRESENT)
152                         if (!prs_uint8s(False, "inh_guid", ps, depth, psa->inh_guid.info, GUID_SIZE))
153                                 return False;
154
155                 if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
156                         return False;
157         }
158
159         if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
160                 return False;
161         return True;
162 }
163
164 /*******************************************************************
165  adds new SID with its permissions to ACE list
166 ********************************************************************/
167
168 NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, size_t *num, DOM_SID *sid, uint32 mask)
169 {
170         int i = 0;
171         
172         if (!ctx || !new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
173
174         *num += 1;
175         
176         if((new[0] = (SEC_ACE *) talloc_zero(ctx, *num * sizeof(SEC_ACE))) == 0)
177                 return NT_STATUS_NO_MEMORY;
178
179         for (i = 0; i < *num - 1; i ++)
180                 sec_ace_copy(&(*new)[i], &old[i]);
181
182         (*new)[i].type  = 0;
183         (*new)[i].flags = 0;
184         (*new)[i].size  = SEC_ACE_HEADER_SIZE + sid_size(sid);
185         (*new)[i].info.mask = mask;
186         sid_copy(&(*new)[i].trustee, sid);
187         return NT_STATUS_OK;
188 }
189
190 /*******************************************************************
191   modify SID's permissions at ACL 
192 ********************************************************************/
193
194 NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
195 {
196         int i = 0;
197
198         if (!ace || !sid)  return NT_STATUS_INVALID_PARAMETER;
199
200         for (i = 0; i < num; i ++) {
201                 if (sid_compare(&ace[i].trustee, sid) == 0) {
202                         ace[i].info.mask = mask;
203                         return NT_STATUS_OK;
204                 }
205         }
206         return NT_STATUS_NOT_FOUND;
207 }
208
209 /*******************************************************************
210  delete SID from ACL
211 ********************************************************************/
212
213 NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, size_t *num, DOM_SID *sid)
214 {
215         int i     = 0;
216         int n_del = 0;
217
218         if (!ctx || !new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
219
220         if((new[0] = (SEC_ACE *) talloc_zero(ctx, *num * sizeof(SEC_ACE))) == 0)
221                 return NT_STATUS_NO_MEMORY;
222
223         for (i = 0; i < *num; i ++) {
224                 if (sid_compare(&old[i].trustee, sid) != 0)
225                         sec_ace_copy(&(*new)[i], &old[i]);
226                 else
227                         n_del ++;
228         }
229         if (n_del == 0)
230                 return NT_STATUS_NOT_FOUND;
231         else {
232                 *num -= n_del;
233                 return NT_STATUS_OK;
234         }
235 }
236
237 /*******************************************************************
238  Create a SEC_ACL structure.  
239 ********************************************************************/
240
241 SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
242 {
243         SEC_ACL *dst;
244         int i;
245
246         if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
247                 return NULL;
248
249         dst->revision = revision;
250         dst->num_aces = num_aces;
251         dst->size = SEC_ACL_HEADER_SIZE;
252
253         /* Now we need to return a non-NULL address for the ace list even
254            if the number of aces required is zero.  This is because there
255            is a distinct difference between a NULL ace and an ace with zero
256            entries in it.  This is achieved by checking that num_aces is a
257            positive number. */
258
259         if ((num_aces) && 
260             ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) 
261              == NULL)) {
262                 return NULL;
263         }
264         
265         for (i = 0; i < num_aces; i++) {
266                 dst->ace[i] = ace_list[i]; /* Structure copy. */
267                 dst->size += ace_list[i].size;
268         }
269
270         return dst;
271 }
272
273 /*******************************************************************
274  Duplicate a SEC_ACL structure.  
275 ********************************************************************/
276
277 SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
278 {
279         if(src == NULL)
280                 return NULL;
281
282         return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
283 }
284
285 /*******************************************************************
286  Reads or writes a SEC_ACL structure.  
287
288  First of the xx_io_xx functions that allocates its data structures
289  for you as it reads them.
290 ********************************************************************/
291
292 BOOL sec_io_acl(char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
293 {
294         int i;
295         uint32 old_offset;
296         uint32 offset_acl_size;
297         SEC_ACL *psa;
298
299         if (ppsa == NULL)
300                 return False;
301
302         psa = *ppsa;
303
304         if(UNMARSHALLING(ps) && psa == NULL) {
305                 /*
306                  * This is a read and we must allocate the stuct to read into.
307                  */
308                 if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
309                         return False;
310                 *ppsa = psa;
311         }
312
313         prs_debug(ps, depth, desc, "sec_io_acl");
314         depth++;
315
316         if(!prs_align(ps))
317                 return False;
318         
319         old_offset = prs_offset(ps);
320
321         if(!prs_uint16("revision", ps, depth, &psa->revision))
322                 return False;
323
324         if(!prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size))
325                 return False;
326
327         if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
328                 return False;
329
330         if (UNMARSHALLING(ps)) {
331                 /*
332                  * Even if the num_aces is zero, allocate memory as there's a difference
333                  * between a non-present DACL (allow all access) and a DACL with no ACE's
334                  * (allow no access).
335                  */
336                 if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
337                         return False;
338         }
339
340         for (i = 0; i < psa->num_aces; i++) {
341                 fstring tmp;
342                 slprintf(tmp, sizeof(tmp)-1, "ace_list[%02d]: ", i);
343                 if(!sec_io_ace(tmp, &psa->ace[i], ps, depth))
344                         return False;
345         }
346
347         if(!prs_align(ps))
348                 return False;
349
350         if(!prs_uint16_post("size     ", ps, depth, &psa->size, offset_acl_size, old_offset))
351                 return False;
352
353         return True;
354 }
355
356 /*******************************************************************
357  Works out the linearization size of a SEC_DESC.
358 ********************************************************************/
359
360 size_t sec_desc_size(SEC_DESC *psd)
361 {
362         size_t offset;
363
364         if (!psd) return 0;
365
366         offset = SEC_DESC_HEADER_SIZE;
367
368         if (psd->owner_sid != NULL)
369                 offset += ((sid_size(psd->owner_sid) + 3) & ~3);
370
371         if (psd->grp_sid != NULL)
372                 offset += ((sid_size(psd->grp_sid) + 3) & ~3);
373
374         if (psd->sacl != NULL)
375                 offset += ((psd->sacl->size + 3) & ~3);
376
377         if (psd->dacl != NULL)
378                 offset += ((psd->dacl->size + 3) & ~3);
379
380         return offset;
381 }
382
383 /*******************************************************************
384  Compares two SEC_ACE structures
385 ********************************************************************/
386
387 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
388 {
389         /* Trivial case */
390
391         if (!s1 && !s2) return True;
392
393         /* Check top level stuff */
394
395         if (s1->type != s2->type || s1->flags != s2->flags ||
396             s1->info.mask != s2->info.mask) {
397                 return False;
398         }
399
400         /* Check SID */
401
402         if (!sid_equal(&s1->trustee, &s2->trustee)) {
403                 return False;
404         }
405
406         return True;
407 }
408
409 /*******************************************************************
410  Compares two SEC_ACL structures
411 ********************************************************************/
412
413 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
414 {
415         int i, j;
416
417         /* Trivial cases */
418
419         if (!s1 && !s2) return True;
420         if (!s1 || !s2) return False;
421
422         /* Check top level stuff */
423
424         if (s1->revision != s2->revision) {
425                 DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n",
426                            s1->revision, s2->revision));
427                 return False;
428         }
429
430         if (s1->num_aces != s2->num_aces) {
431                 DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n",
432                            s1->revision, s2->revision));
433                 return False;
434         }
435
436         /* The ACEs could be in any order so check each ACE in s1 against 
437            each ACE in s2. */
438
439         for (i = 0; i < s1->num_aces; i++) {
440                 BOOL found = False;
441
442                 for (j = 0; j < s2->num_aces; j++) {
443                         if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) {
444                                 found = True;
445                                 break;
446                         }
447                 }
448
449                 if (!found) return False;
450         }
451
452         return True;
453 }
454
455 /*******************************************************************
456  Compares two SEC_DESC structures
457 ********************************************************************/
458
459 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
460 {
461         /* Trivial case */
462
463         if (!s1 && !s2) {
464                 goto done;
465         }
466
467         /* Check top level stuff */
468
469         if (s1->revision != s2->revision) {
470                 DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n",
471                            s1->revision, s2->revision));
472                 return False;
473         }
474
475         if (s1->type!= s2->type) {
476                 DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n",
477                            s1->type, s2->type));
478                 return False;
479         }
480
481         /* Check owner and group */
482
483         if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
484                 fstring str1, str2;
485
486                 sid_to_string(str1, s1->owner_sid);
487                 sid_to_string(str2, s2->owner_sid);
488
489                 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
490                            str1, str2));
491                 return False;
492         }
493
494         if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
495                 fstring str1, str2;
496
497                 sid_to_string(str1, s1->grp_sid);
498                 sid_to_string(str2, s2->grp_sid);
499
500                 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
501                            str1, str2));
502                 return False;
503         }
504
505         /* Check ACLs present in one but not the other */
506
507         if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) ||
508             (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) {
509                 DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n"));
510                 return False;
511         }
512
513         /* Sigh - we have to do it the hard way by iterating over all
514            the ACEs in the ACLs */
515
516         if (!sec_acl_equal(s1->dacl, s2->dacl) ||
517             !sec_acl_equal(s1->sacl, s2->sacl)) {
518                 DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n"));
519                 return False;
520         }
521
522  done:
523         DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
524         return True;
525 }
526
527 /*******************************************************************
528  Merge part of security descriptor old_sec in to the empty sections of 
529  security descriptor new_sec.
530 ********************************************************************/
531
532 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
533 {
534         DOM_SID *owner_sid, *group_sid;
535         SEC_DESC_BUF *return_sdb;
536         SEC_ACL *dacl, *sacl;
537         SEC_DESC *psd = NULL;
538         uint16 secdesc_type;
539         size_t secdesc_size;
540
541         /* Copy over owner and group sids.  There seems to be no flag for
542            this so just check the pointer values. */
543
544         owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
545                 old_sdb->sec->owner_sid;
546
547         group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
548                 old_sdb->sec->grp_sid;
549         
550         secdesc_type = new_sdb->sec->type;
551
552         /* Ignore changes to the system ACL.  This has the effect of making
553            changes through the security tab audit button not sticking. 
554            Perhaps in future Samba could implement these settings somehow. */
555
556         sacl = NULL;
557         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
558
559         /* Copy across discretionary ACL */
560
561         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
562                 dacl = new_sdb->sec->dacl;
563         } else {
564                 dacl = old_sdb->sec->dacl;
565         }
566
567         /* Create new security descriptor from bits */
568
569         psd = make_sec_desc(ctx, new_sdb->sec->revision, 
570                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
571
572         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
573
574         return(return_sdb);
575 }
576
577 /*******************************************************************
578  Tallocs a duplicate SID. 
579 ********************************************************************/ 
580
581 static DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src)
582 {
583   DOM_SID *dst;
584
585   if(!src)
586     return NULL;
587
588   if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) {
589     sid_copy( dst, src);
590   }
591
592   return dst;
593 }
594
595 /*******************************************************************
596  Creates a SEC_DESC structure
597 ********************************************************************/
598
599 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, 
600                         DOM_SID *owner_sid, DOM_SID *grp_sid,
601                         SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
602 {
603         SEC_DESC *dst;
604         uint32 offset     = 0;
605         uint32 offset_sid = SEC_DESC_HEADER_SIZE;
606         uint32 offset_acl = 0;
607
608         *sd_size = 0;
609
610         if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
611                 return NULL;
612
613         dst->revision = revision;
614         dst->type     = SEC_DESC_SELF_RELATIVE;
615
616         if (sacl) dst->type |= SEC_DESC_SACL_PRESENT;
617         if (dacl) dst->type |= SEC_DESC_DACL_PRESENT;
618
619         dst->off_owner_sid = 0;
620         dst->off_grp_sid   = 0;
621         dst->off_sacl      = 0;
622         dst->off_dacl      = 0;
623
624         if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
625                 goto error_exit;
626
627         if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
628                 goto error_exit;
629
630         if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
631                 goto error_exit;
632
633         if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
634                 goto error_exit;
635
636         offset = 0;
637
638         /*
639          * Work out the linearization sizes.
640          */
641         if (dst->owner_sid != NULL) {
642
643                 if (offset == 0)
644                         offset = SEC_DESC_HEADER_SIZE;
645
646                 offset += ((sid_size(dst->owner_sid) + 3) & ~3);
647         }
648
649         if (dst->grp_sid != NULL) {
650
651                 if (offset == 0)
652                         offset = SEC_DESC_HEADER_SIZE;
653
654                 offset += ((sid_size(dst->grp_sid) + 3) & ~3);
655         }
656
657         if (dst->sacl != NULL) {
658
659                 offset_acl = SEC_DESC_HEADER_SIZE;
660
661                 dst->off_sacl  = offset_acl;
662                 offset_acl    += ((dst->sacl->size + 3) & ~3);
663                 offset        += dst->sacl->size;
664                 offset_sid    += dst->sacl->size;
665         }
666
667         if (dst->dacl != NULL) {
668
669                 if (offset_acl == 0)
670                         offset_acl = SEC_DESC_HEADER_SIZE;
671
672                 dst->off_dacl  = offset_acl;
673                 offset_acl    += ((dst->dacl->size + 3) & ~3);
674                 offset        += dst->dacl->size;
675                 offset_sid    += dst->dacl->size;
676         }
677
678         *sd_size = (size_t)((offset == 0) ? SEC_DESC_HEADER_SIZE : offset);
679
680         if (dst->owner_sid != NULL) {
681                 dst->off_owner_sid = offset_sid;
682                 dst->off_grp_sid = offset_sid + sid_size(dst->owner_sid);
683         }
684         else
685                 if (dst->grp_sid != NULL)
686                         dst->off_grp_sid = offset_sid;
687
688         return dst;
689
690 error_exit:
691
692         *sd_size = 0;
693         return NULL;
694 }
695
696 /*******************************************************************
697  Duplicate a SEC_DESC structure.  
698 ********************************************************************/
699
700 SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src)
701 {
702         size_t dummy;
703
704         if(src == NULL)
705                 return NULL;
706
707         return make_sec_desc( ctx, src->revision, 
708                                 src->owner_sid, src->grp_sid, src->sacl,
709                                 src->dacl, &dummy);
710 }
711
712 /*******************************************************************
713  Creates a SEC_DESC structure with typical defaults.
714 ********************************************************************/
715
716 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
717                                  SEC_ACL *dacl, size_t *sd_size)
718 {
719         return make_sec_desc(ctx, SEC_DESC_REVISION,
720                              owner_sid, grp_sid, NULL, dacl, sd_size);
721 }
722
723 /*******************************************************************
724  Reads or writes a SEC_DESC structure.
725  If reading and the *ppsd = NULL, allocates the structure.
726 ********************************************************************/
727
728 BOOL sec_io_desc(char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
729 {
730         uint32 old_offset;
731         uint32 max_offset = 0; /* after we're done, move offset to end */
732         uint32 tmp_offset = 0;
733         
734         SEC_DESC *psd;
735
736         if (ppsd == NULL)
737                 return False;
738
739         psd = *ppsd;
740
741         if (psd == NULL) {
742                 if(UNMARSHALLING(ps)) {
743                         if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
744                                 return False;
745                         *ppsd = psd;
746                 } else {
747                         /* Marshalling - just ignore. */
748                         return True;
749                 }
750         }
751
752         prs_debug(ps, depth, desc, "sec_io_desc");
753         depth++;
754
755 #if 0   /* JERRY */
756         /*
757          * if alignment is needed, should be done by the the 
758          * caller.  Not here.  This caused me problems when marshalling
759          * printer info into a buffer.   --jerry
760          */
761         if(!prs_align(ps))
762                 return False;
763 #endif
764         
765         /* start of security descriptor stored for back-calc offset purposes */
766         old_offset = prs_offset(ps);
767
768         if(!prs_uint16("revision ", ps, depth, &psd->revision))
769                 return False;
770
771         if(!prs_uint16("type     ", ps, depth, &psd->type))
772                 return False;
773
774         if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
775                 return False;
776
777         if(!prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid))
778                 return False;
779
780         if(!prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl))
781                 return False;
782
783         if(!prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
784                 return False;
785
786         max_offset = MAX(max_offset, prs_offset(ps));
787
788         if (psd->off_owner_sid != 0) {
789
790                 if (UNMARSHALLING(ps)) {
791                         if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
792                                 return False;
793                         /* reading */
794                         if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
795                                 return False;
796                 }
797
798                 tmp_offset = ps->data_offset;
799                 ps->data_offset = psd->off_owner_sid;
800
801                 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
802                         return False;
803                 if(!prs_align(ps))
804                         return False;
805
806                 ps->data_offset = tmp_offset;
807         }
808
809         max_offset = MAX(max_offset, prs_offset(ps));
810
811         if (psd->off_grp_sid != 0) {
812
813                 if (UNMARSHALLING(ps)) {
814                         /* reading */
815                         if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
816                                 return False;
817                         if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
818                                 return False;
819                 }
820
821                 tmp_offset = ps->data_offset;
822                 ps->data_offset = psd->off_grp_sid;
823
824                 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
825                         return False;
826                 if(!prs_align(ps))
827                         return False;
828
829                 ps->data_offset = tmp_offset;
830         }
831
832         max_offset = MAX(max_offset, prs_offset(ps));
833
834         if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
835                 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
836                         return False;
837                 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
838                         return False;
839                 if(!prs_align(ps))
840                         return False;
841         }
842
843         max_offset = MAX(max_offset, prs_offset(ps));
844
845         if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
846                 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
847                         return False;
848                 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
849                         return False;
850                 if(!prs_align(ps))
851                         return False;
852         }
853
854         max_offset = MAX(max_offset, prs_offset(ps));
855
856         if(!prs_set_offset(ps, max_offset))
857                 return False;
858         return True;
859 }
860
861 /*******************************************************************
862  Creates a SEC_DESC_BUF structure.
863 ********************************************************************/
864
865 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
866 {
867         SEC_DESC_BUF *dst;
868
869         if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
870                 return NULL;
871
872         /* max buffer size (allocated size) */
873         dst->max_len = (uint32)len;
874         dst->len = (uint32)len;
875         
876         if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
877                 return NULL;
878         }
879
880         dst->ptr = 0x1;
881
882         return dst;
883 }
884
885 /*******************************************************************
886  Duplicates a SEC_DESC_BUF structure.
887 ********************************************************************/
888
889 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
890 {
891         if(src == NULL)
892                 return NULL;
893
894         return make_sec_desc_buf( ctx, src->len, src->sec);
895 }
896
897 /*******************************************************************
898  Reads or writes a SEC_DESC_BUF structure.
899 ********************************************************************/
900
901 BOOL sec_io_desc_buf(char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
902 {
903         uint32 off_len;
904         uint32 off_max_len;
905         uint32 old_offset;
906         uint32 size;
907         SEC_DESC_BUF *psdb;
908
909         if (ppsdb == NULL)
910                 return False;
911
912         psdb = *ppsdb;
913
914         if (UNMARSHALLING(ps) && psdb == NULL) {
915                 if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
916                         return False;
917                 *ppsdb = psdb;
918         }
919
920         prs_debug(ps, depth, desc, "sec_io_desc_buf");
921         depth++;
922
923         if(!prs_align(ps))
924                 return False;
925         
926         if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
927                 return False;
928
929         if(!prs_uint32    ("ptr  ", ps, depth, &psdb->ptr))
930                 return False;
931
932         if(!prs_uint32_pre("len    ", ps, depth, &psdb->len, &off_len))
933                 return False;
934
935         old_offset = prs_offset(ps);
936
937         /* reading, length is non-zero; writing, descriptor is non-NULL */
938         if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
939                 if(!sec_io_desc("sec   ", &psdb->sec, ps, depth))
940                         return False;
941         }
942
943         if(!prs_align(ps))
944                 return False;
945         
946         size = prs_offset(ps) - old_offset;
947         if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
948                 return False;
949
950         if(!prs_uint32_post("len    ", ps, depth, &psdb->len, off_len, size))
951                 return False;
952
953         return True;
954 }
955
956 /*******************************************************************
957  adds new SID with its permissions to SEC_DESC
958 ********************************************************************/
959
960 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
961 {
962         SEC_DESC *sd   = 0;
963         SEC_ACL  *dacl = 0;
964         SEC_ACE  *ace  = 0;
965         NTSTATUS  status;
966
967         *sd_size = 0;
968
969         if (!ctx || !psd || !sid || !sd_size)  return NT_STATUS_INVALID_PARAMETER;
970
971         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
972         
973         if (!NT_STATUS_IS_OK(status))
974                 return status;
975
976         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
977                 return NT_STATUS_UNSUCCESSFUL;
978         
979         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->owner_sid, 
980                 psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
981                 return NT_STATUS_UNSUCCESSFUL;
982
983         *psd = sd;
984          sd  = 0;
985         return NT_STATUS_OK;
986 }
987
988 /*******************************************************************
989  modify SID's permissions at SEC_DESC
990 ********************************************************************/
991
992 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
993 {
994         NTSTATUS status;
995
996         if (!sd || !sid) return NT_STATUS_INVALID_PARAMETER;
997
998         status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
999
1000         if (!NT_STATUS_IS_OK(status))
1001                 return status;
1002         
1003         return NT_STATUS_OK;
1004 }
1005
1006 /*******************************************************************
1007  delete SID from SEC_DESC
1008 ********************************************************************/
1009
1010 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
1011 {
1012         SEC_DESC *sd   = 0;
1013         SEC_ACL  *dacl = 0;
1014         SEC_ACE  *ace  = 0;
1015         NTSTATUS  status;
1016
1017         *sd_size = 0;
1018         
1019         if (!ctx || !psd[0] || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER;
1020
1021         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
1022
1023         if (!NT_STATUS_IS_OK(status))
1024                 return status;
1025
1026         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
1027                 return NT_STATUS_UNSUCCESSFUL;
1028         
1029         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->owner_sid, 
1030                 psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
1031                 return NT_STATUS_UNSUCCESSFUL;
1032
1033         *psd = sd;
1034          sd  = 0;
1035         return NT_STATUS_OK;
1036 }