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