This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[metze/samba/wip.git] / source3 / rpc_parse / parse_sec.c
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-2003.
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.
14  *  
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.
19  *  
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.
23  */
24
25 #include "includes.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_PARSE
29
30 /*******************************************************************
31  Sets up a SEC_ACCESS structure.
32 ********************************************************************/
33
34 void init_sec_access(SEC_ACCESS *t, uint32 mask)
35 {
36         t->mask = mask;
37 }
38
39 /*******************************************************************
40  Reads or writes a SEC_ACCESS structure.
41 ********************************************************************/
42
43 BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth)
44 {
45         if (t == NULL)
46                 return False;
47
48         prs_debug(ps, depth, desc, "sec_io_access");
49         depth++;
50         
51         if(!prs_uint32("mask", ps, depth, &t->mask))
52                 return False;
53
54         return True;
55 }
56
57 /*******************************************************************
58  Check if ACE has OBJECT type.
59 ********************************************************************/
60
61 BOOL sec_ace_object(uint8 type)
62 {
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;
68         }
69         return False;
70 }
71
72 /*******************************************************************
73  copy a SEC_ACE structure.
74 ********************************************************************/
75 void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src)
76 {
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);
85 }
86
87 /*******************************************************************
88  Sets up a SEC_ACE structure.
89 ********************************************************************/
90
91 void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag)
92 {
93         t->type = type;
94         t->flags = flag;
95         t->size = sid_size(sid) + 8;
96         t->info = mask;
97
98         ZERO_STRUCTP(&t->trustee);
99         sid_copy(&t->trustee, sid);
100 }
101
102 /*******************************************************************
103  Reads or writes a SEC_ACE structure.
104 ********************************************************************/
105
106 BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth)
107 {
108         uint32 old_offset;
109         uint32 offset_ace_size;
110
111         if (psa == NULL)
112                 return False;
113
114         prs_debug(ps, depth, desc, "sec_io_ace");
115         depth++;
116         
117         old_offset = prs_offset(ps);
118
119         if(!prs_uint8("type ", ps, depth, &psa->type))
120                 return False;
121
122         if(!prs_uint8("flags", ps, depth, &psa->flags))
123                 return False;
124
125         if(!prs_uint16_pre("size ", ps, depth, &psa->size, &offset_ace_size))
126                 return False;
127
128         if(!sec_io_access("info ", &psa->info, ps, depth))
129                 return False;
130
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;
138
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;
142
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;
146
147                 if(!smb_io_dom_sid("trustee  ", &psa->trustee , ps, depth))
148                         return False;
149         }
150
151         if(!prs_uint16_post("size ", ps, depth, &psa->size, offset_ace_size, old_offset))
152                 return False;
153         return True;
154 }
155
156 /*******************************************************************
157  adds new SID with its permissions to ACE list
158 ********************************************************************/
159
160 NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask)
161 {
162         unsigned int i = 0;
163         
164         if (!ctx || !new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
165
166         *num += 1;
167         
168         if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0)
169                 return NT_STATUS_NO_MEMORY;
170
171         for (i = 0; i < *num - 1; i ++)
172                 sec_ace_copy(&(*new)[i], &old[i]);
173
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;
180 }
181
182 /*******************************************************************
183   modify SID's permissions at ACL 
184 ********************************************************************/
185
186 NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask)
187 {
188         unsigned int i = 0;
189
190         if (!ace || !sid)  return NT_STATUS_INVALID_PARAMETER;
191
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;
196                 }
197         }
198         return NT_STATUS_NOT_FOUND;
199 }
200
201 /*******************************************************************
202  delete SID from ACL
203 ********************************************************************/
204
205 static NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, uint32 *num, DOM_SID *sid)
206 {
207         unsigned int i     = 0;
208         unsigned int n_del = 0;
209
210         if (!ctx || !new || !old || !sid || !num)  return NT_STATUS_INVALID_PARAMETER;
211
212         if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0)
213                 return NT_STATUS_NO_MEMORY;
214
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 ++;
220         }
221         if (n_del == 0)
222                 return NT_STATUS_NOT_FOUND;
223         else {
224                 *num -= n_del;
225                 return NT_STATUS_OK;
226         }
227 }
228
229 /*******************************************************************
230  Create a SEC_ACL structure.  
231 ********************************************************************/
232
233 SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list)
234 {
235         SEC_ACL *dst;
236         int i;
237
238         if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL)
239                 return NULL;
240
241         dst->revision = revision;
242         dst->num_aces = num_aces;
243         dst->size = SEC_ACL_HEADER_SIZE;
244
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. */
250
251         if ((num_aces) && 
252             ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) 
253              == NULL)) {
254                 return NULL;
255         }
256         
257         for (i = 0; i < num_aces; i++) {
258                 dst->ace[i] = ace_list[i]; /* Structure copy. */
259                 dst->size += ace_list[i].size;
260         }
261
262         return dst;
263 }
264
265 /*******************************************************************
266  Duplicate a SEC_ACL structure.  
267 ********************************************************************/
268
269 SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src)
270 {
271         if(src == NULL)
272                 return NULL;
273
274         return make_sec_acl(ctx, src->revision, src->num_aces, src->ace);
275 }
276
277 /*******************************************************************
278  Reads or writes a SEC_ACL structure.  
279
280  First of the xx_io_xx functions that allocates its data structures
281  for you as it reads them.
282 ********************************************************************/
283
284 BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth)
285 {
286         unsigned int i;
287         uint32 old_offset;
288         uint32 offset_acl_size;
289         SEC_ACL *psa;
290
291         /*
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
296          */
297
298         if (ppsa == NULL)
299                 return False;
300
301         psa = *ppsa;
302
303         if(UNMARSHALLING(ps) && psa == NULL) {
304                 /*
305                  * This is a read and we must allocate the stuct to read into.
306                  */
307                 if((psa = (SEC_ACL *)prs_alloc_mem(ps, sizeof(SEC_ACL))) == NULL)
308                         return False;
309                 *ppsa = psa;
310         }
311
312         prs_debug(ps, depth, desc, "sec_io_acl");
313         depth++;
314         
315         old_offset = prs_offset(ps);
316
317         if(!prs_uint16("revision", ps, depth, &psa->revision))
318                 return False;
319
320         if(!prs_uint16_pre("size     ", ps, depth, &psa->size, &offset_acl_size))
321                 return False;
322
323         if(!prs_uint32("num_aces ", ps, depth, &psa->num_aces))
324                 return False;
325
326         if (UNMARSHALLING(ps)) {
327                 /*
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).
331                  */
332                 if((psa->ace = (SEC_ACE *)prs_alloc_mem(ps,sizeof(psa->ace[0]) * (psa->num_aces+1))) == NULL)
333                         return False;
334         }
335
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;
341         }
342
343         if(!prs_uint16_post("size     ", ps, depth, &psa->size, offset_acl_size, old_offset))
344                 return False;
345
346         return True;
347 }
348
349 /*******************************************************************
350  Works out the linearization size of a SEC_DESC.
351 ********************************************************************/
352
353 size_t sec_desc_size(SEC_DESC *psd)
354 {
355         size_t offset;
356
357         if (!psd) return 0;
358
359         offset = SEC_DESC_HEADER_SIZE;
360
361         /* don't align */
362
363         if (psd->owner_sid != NULL)
364                 offset += sid_size(psd->owner_sid);
365
366         if (psd->grp_sid != NULL)
367                 offset += sid_size(psd->grp_sid);
368
369         if (psd->sacl != NULL)
370                 offset += psd->sacl->size;
371
372         if (psd->dacl != NULL)
373                 offset += psd->dacl->size;
374
375         return offset;
376 }
377
378 /*******************************************************************
379  Compares two SEC_ACE structures
380 ********************************************************************/
381
382 BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2)
383 {
384         /* Trivial case */
385
386         if (!s1 && !s2) return True;
387
388         /* Check top level stuff */
389
390         if (s1->type != s2->type || s1->flags != s2->flags ||
391             s1->info.mask != s2->info.mask) {
392                 return False;
393         }
394
395         /* Check SID */
396
397         if (!sid_equal(&s1->trustee, &s2->trustee)) {
398                 return False;
399         }
400
401         return True;
402 }
403
404 /*******************************************************************
405  Compares two SEC_ACL structures
406 ********************************************************************/
407
408 BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2)
409 {
410         unsigned int i, j;
411
412         /* Trivial cases */
413
414         if (!s1 && !s2) return True;
415         if (!s1 || !s2) return False;
416
417         /* Check top level stuff */
418
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;
423         }
424
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;
429         }
430
431         /* The ACEs could be in any order so check each ACE in s1 against 
432            each ACE in s2. */
433
434         for (i = 0; i < s1->num_aces; i++) {
435                 BOOL found = False;
436
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;
441                         }
442                 }
443
444                 if (!found) return False;
445         }
446
447         return True;
448 }
449
450 /*******************************************************************
451  Compares two SEC_DESC structures
452 ********************************************************************/
453
454 BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2)
455 {
456         /* Trivial case */
457
458         if (!s1 && !s2) {
459                 goto done;
460         }
461
462         /* Check top level stuff */
463
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;
468         }
469
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;
474         }
475
476         /* Check owner and group */
477
478         if (!sid_equal(s1->owner_sid, s2->owner_sid)) {
479                 fstring str1, str2;
480
481                 sid_to_string(str1, s1->owner_sid);
482                 sid_to_string(str2, s2->owner_sid);
483
484                 DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n",
485                            str1, str2));
486                 return False;
487         }
488
489         if (!sid_equal(s1->grp_sid, s2->grp_sid)) {
490                 fstring str1, str2;
491
492                 sid_to_string(str1, s1->grp_sid);
493                 sid_to_string(str2, s2->grp_sid);
494
495                 DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n",
496                            str1, str2));
497                 return False;
498         }
499
500         /* Check ACLs present in one but not the other */
501
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;
506         }
507
508         /* Sigh - we have to do it the hard way by iterating over all
509            the ACEs in the ACLs */
510
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;
515         }
516
517  done:
518         DEBUG(10, ("sec_desc_equal(): secdescs are identical\n"));
519         return True;
520 }
521
522 /*******************************************************************
523  Merge part of security descriptor old_sec in to the empty sections of 
524  security descriptor new_sec.
525 ********************************************************************/
526
527 SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb)
528 {
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;
535
536         /* Copy over owner and group sids.  There seems to be no flag for
537            this so just check the pointer values. */
538
539         owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid :
540                 old_sdb->sec->owner_sid;
541
542         group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid :
543                 old_sdb->sec->grp_sid;
544         
545         secdesc_type = new_sdb->sec->type;
546
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. */
550
551         sacl = NULL;
552         secdesc_type &= ~SEC_DESC_SACL_PRESENT;
553
554         /* Copy across discretionary ACL */
555
556         if (secdesc_type & SEC_DESC_DACL_PRESENT) {
557                 dacl = new_sdb->sec->dacl;
558         } else {
559                 dacl = old_sdb->sec->dacl;
560         }
561
562         /* Create new security descriptor from bits */
563
564         psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type,
565                             owner_sid, group_sid, sacl, dacl, &secdesc_size);
566
567         return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd);
568
569         return(return_sdb);
570 }
571
572 /*******************************************************************
573  Creates a SEC_DESC structure
574 ********************************************************************/
575
576 SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type,
577                         DOM_SID *owner_sid, DOM_SID *grp_sid,
578                         SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size)
579 {
580         SEC_DESC *dst;
581         uint32 offset     = 0;
582
583         *sd_size = 0;
584
585         if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL)
586                 return NULL;
587
588         dst->revision = revision;
589         dst->type = type;
590
591         if (sacl)
592                 dst->type |= SEC_DESC_SACL_PRESENT;
593         if (dacl)
594                 dst->type |= SEC_DESC_DACL_PRESENT;
595
596         dst->off_owner_sid = 0;
597         dst->off_grp_sid   = 0;
598         dst->off_sacl      = 0;
599         dst->off_dacl      = 0;
600
601         if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL))
602                 goto error_exit;
603
604         if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL))
605                 goto error_exit;
606
607         if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL))
608                 goto error_exit;
609
610         if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL))
611                 goto error_exit;
612
613         offset = SEC_DESC_HEADER_SIZE;
614
615         /*
616          * Work out the linearization sizes.
617          */
618
619         if (dst->sacl != NULL) {
620                 dst->off_sacl = offset;
621                 offset += dst->sacl->size;
622         }
623
624         if (dst->dacl != NULL) {
625                 dst->off_dacl = offset;
626                 offset += dst->dacl->size;
627         }
628
629         if (dst->owner_sid != NULL) {
630                 dst->off_owner_sid = offset;
631                 offset += sid_size(dst->owner_sid);
632         }
633
634         if (dst->grp_sid != NULL) {
635                 dst->off_grp_sid = offset;
636                 offset += sid_size(dst->grp_sid);
637         }
638
639         *sd_size = (size_t)offset;
640         return dst;
641
642 error_exit:
643
644         *sd_size = 0;
645         return NULL;
646 }
647
648 /*******************************************************************
649  Duplicate a SEC_DESC structure.  
650 ********************************************************************/
651
652 SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src)
653 {
654         size_t dummy;
655
656         if(src == NULL)
657                 return NULL;
658
659         return make_sec_desc( ctx, src->revision, src->type,
660                                 src->owner_sid, src->grp_sid, src->sacl,
661                                 src->dacl, &dummy);
662 }
663
664 /*******************************************************************
665  Creates a SEC_DESC structure with typical defaults.
666 ********************************************************************/
667
668 SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid,
669                                  SEC_ACL *dacl, size_t *sd_size)
670 {
671         return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
672                              owner_sid, grp_sid, NULL, dacl, sd_size);
673 }
674
675 /*******************************************************************
676  Reads or writes a SEC_DESC structure.
677  If reading and the *ppsd = NULL, allocates the structure.
678 ********************************************************************/
679
680 BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth)
681 {
682         uint32 old_offset;
683         uint32 max_offset = 0; /* after we're done, move offset to end */
684         uint32 tmp_offset = 0;
685         
686         SEC_DESC *psd;
687
688         if (ppsd == NULL)
689                 return False;
690
691         psd = *ppsd;
692
693         if (psd == NULL) {
694                 if(UNMARSHALLING(ps)) {
695                         if((psd = (SEC_DESC *)prs_alloc_mem(ps,sizeof(SEC_DESC))) == NULL)
696                                 return False;
697                         *ppsd = psd;
698                 } else {
699                         /* Marshalling - just ignore. */
700                         return True;
701                 }
702         }
703
704         prs_debug(ps, depth, desc, "sec_io_desc");
705         depth++;
706
707 #if 0   
708         /*
709          * if alignment is needed, should be done by the the 
710          * caller.  Not here.  This caused me problems when marshalling
711          * printer info into a buffer.   --jerry
712          */
713         if(!prs_align(ps))
714                 return False;
715 #endif
716         
717         /* start of security descriptor stored for back-calc offset purposes */
718         old_offset = prs_offset(ps);
719
720         if(!prs_uint16("revision ", ps, depth, &psd->revision))
721                 return False;
722
723         if(!prs_uint16("type     ", ps, depth, &psd->type))
724                 return False;
725
726         if(!prs_uint32("off_owner_sid", ps, depth, &psd->off_owner_sid))
727                 return False;
728
729         if(!prs_uint32("off_grp_sid  ", ps, depth, &psd->off_grp_sid))
730                 return False;
731
732         if(!prs_uint32("off_sacl     ", ps, depth, &psd->off_sacl))
733                 return False;
734
735         if(!prs_uint32("off_dacl     ", ps, depth, &psd->off_dacl))
736                 return False;
737
738         max_offset = MAX(max_offset, prs_offset(ps));
739
740         if (psd->off_owner_sid != 0) {
741
742                 tmp_offset = prs_offset(ps);
743                 if(!prs_set_offset(ps, old_offset + psd->off_owner_sid))
744                         return False;
745
746                 if (UNMARSHALLING(ps)) {
747                         /* reading */
748                         if((psd->owner_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->owner_sid))) == NULL)
749                                 return False;
750                 }
751
752                 if(!smb_io_dom_sid("owner_sid ", psd->owner_sid , ps, depth))
753                         return False;
754
755                 max_offset = MAX(max_offset, prs_offset(ps));
756
757                 if (!prs_set_offset(ps,tmp_offset))
758                         return False;
759         }
760
761         if (psd->off_grp_sid != 0) {
762
763                 tmp_offset = prs_offset(ps);
764                 if(!prs_set_offset(ps, old_offset + psd->off_grp_sid))
765                         return False;
766
767                 if (UNMARSHALLING(ps)) {
768                         /* reading */
769                         if((psd->grp_sid = (DOM_SID *)prs_alloc_mem(ps,sizeof(*psd->grp_sid))) == NULL)
770                                 return False;
771                 }
772
773                 if(!smb_io_dom_sid("grp_sid", psd->grp_sid, ps, depth))
774                         return False;
775                         
776                 max_offset = MAX(max_offset, prs_offset(ps));
777
778                 if (!prs_set_offset(ps,tmp_offset))
779                         return False;
780         }
781
782         if ((psd->type & SEC_DESC_SACL_PRESENT) && psd->off_sacl) {
783                 tmp_offset = prs_offset(ps);
784                 if(!prs_set_offset(ps, old_offset + psd->off_sacl))
785                         return False;
786                 if(!sec_io_acl("sacl", &psd->sacl, ps, depth))
787                         return False;
788                 max_offset = MAX(max_offset, prs_offset(ps));
789                 if (!prs_set_offset(ps,tmp_offset))
790                         return False;
791         }
792
793
794         if ((psd->type & SEC_DESC_DACL_PRESENT) && psd->off_dacl != 0) {
795                 tmp_offset = prs_offset(ps);
796                 if(!prs_set_offset(ps, old_offset + psd->off_dacl))
797                         return False;
798                 if(!sec_io_acl("dacl", &psd->dacl, ps, depth))
799                         return False;
800                 max_offset = MAX(max_offset, prs_offset(ps));
801                 if (!prs_set_offset(ps,tmp_offset))
802                         return False;
803         }
804
805         if(!prs_set_offset(ps, max_offset))
806                 return False;
807         return True;
808 }
809
810 /*******************************************************************
811  Creates a SEC_DESC_BUF structure.
812 ********************************************************************/
813
814 SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc)
815 {
816         SEC_DESC_BUF *dst;
817
818         if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL)
819                 return NULL;
820
821         /* max buffer size (allocated size) */
822         dst->max_len = (uint32)len;
823         dst->len = (uint32)len;
824         
825         if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) {
826                 return NULL;
827         }
828
829         dst->ptr = 0x1;
830
831         return dst;
832 }
833
834 /*******************************************************************
835  Duplicates a SEC_DESC_BUF structure.
836 ********************************************************************/
837
838 SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src)
839 {
840         if(src == NULL)
841                 return NULL;
842
843         return make_sec_desc_buf( ctx, src->len, src->sec);
844 }
845
846 /*******************************************************************
847  Reads or writes a SEC_DESC_BUF structure.
848 ********************************************************************/
849
850 BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int depth)
851 {
852         uint32 off_len;
853         uint32 off_max_len;
854         uint32 old_offset;
855         uint32 size;
856         SEC_DESC_BUF *psdb;
857
858         if (ppsdb == NULL)
859                 return False;
860
861         psdb = *ppsdb;
862
863         if (UNMARSHALLING(ps) && psdb == NULL) {
864                 if((psdb = (SEC_DESC_BUF *)prs_alloc_mem(ps,sizeof(SEC_DESC_BUF))) == NULL)
865                         return False;
866                 *ppsdb = psdb;
867         }
868
869         prs_debug(ps, depth, desc, "sec_io_desc_buf");
870         depth++;
871
872         if(!prs_align(ps))
873                 return False;
874         
875         if(!prs_uint32_pre("max_len", ps, depth, &psdb->max_len, &off_max_len))
876                 return False;
877
878         if(!prs_uint32    ("ptr  ", ps, depth, &psdb->ptr))
879                 return False;
880
881         if(!prs_uint32_pre("len    ", ps, depth, &psdb->len, &off_len))
882                 return False;
883
884         old_offset = prs_offset(ps);
885
886         /* reading, length is non-zero; writing, descriptor is non-NULL */
887         if ((UNMARSHALLING(ps) && psdb->len != 0) || (MARSHALLING(ps) && psdb->sec != NULL)) {
888                 if(!sec_io_desc("sec   ", &psdb->sec, ps, depth))
889                         return False;
890         }
891
892         if(!prs_align(ps))
893                 return False;
894         
895         size = prs_offset(ps) - old_offset;
896         if(!prs_uint32_post("max_len", ps, depth, &psdb->max_len, off_max_len, size == 0 ? psdb->max_len : size))
897                 return False;
898
899         if(!prs_uint32_post("len    ", ps, depth, &psdb->len, off_len, size))
900                 return False;
901
902         return True;
903 }
904
905 /*******************************************************************
906  Add a new SID with its permissions to SEC_DESC.
907 ********************************************************************/
908
909 NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size)
910 {
911         SEC_DESC *sd   = 0;
912         SEC_ACL  *dacl = 0;
913         SEC_ACE  *ace  = 0;
914         NTSTATUS  status;
915
916         *sd_size = 0;
917
918         if (!ctx || !psd || !sid || !sd_size)
919                 return NT_STATUS_INVALID_PARAMETER;
920
921         status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask);
922         
923         if (!NT_STATUS_IS_OK(status))
924                 return status;
925
926         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
927                 return NT_STATUS_UNSUCCESSFUL;
928         
929         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
930                 psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
931                 return NT_STATUS_UNSUCCESSFUL;
932
933         *psd = sd;
934          sd  = 0;
935         return NT_STATUS_OK;
936 }
937
938 /*******************************************************************
939  Modify a SID's permissions in a SEC_DESC.
940 ********************************************************************/
941
942 NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask)
943 {
944         NTSTATUS status;
945
946         if (!sd || !sid)
947                 return NT_STATUS_INVALID_PARAMETER;
948
949         status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask);
950
951         if (!NT_STATUS_IS_OK(status))
952                 return status;
953         
954         return NT_STATUS_OK;
955 }
956
957 /*******************************************************************
958  Delete a SID from a SEC_DESC.
959 ********************************************************************/
960
961 NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size)
962 {
963         SEC_DESC *sd   = 0;
964         SEC_ACL  *dacl = 0;
965         SEC_ACE  *ace  = 0;
966         NTSTATUS  status;
967
968         *sd_size = 0;
969         
970         if (!ctx || !psd[0] || !sid || !sd_size)
971                 return NT_STATUS_INVALID_PARAMETER;
972
973         status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid);
974
975         if (!NT_STATUS_IS_OK(status))
976                 return status;
977
978         if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace)))
979                 return NT_STATUS_UNSUCCESSFUL;
980         
981         if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, 
982                 psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size)))
983                 return NT_STATUS_UNSUCCESSFUL;
984
985         *psd = sd;
986          sd  = 0;
987         return NT_STATUS_OK;
988 }
989
990 /*******************************************************************
991   Comparison function to sort non-inherited first.
992 *******************************************************************/
993
994 static int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2)
995 {
996         int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE;
997         int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE;
998
999         if (a1_inh == a2_inh)
1000                 return 0;
1001
1002         if (!a1_inh && a2_inh)
1003                 return -1;
1004         return 1;
1005 }
1006
1007 /*******************************************************************
1008   Comparison function to apply the order explained below in a group.
1009 *******************************************************************/
1010
1011 static int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2)
1012 {
1013         if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
1014                                 (a2->type != SEC_ACE_TYPE_ACCESS_DENIED))
1015                 return -1;
1016
1017         if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) &&
1018                                 (a1->type != SEC_ACE_TYPE_ACCESS_DENIED))
1019                 return 1;
1020
1021         /* Both access denied or access allowed. */
1022
1023         /* 1. ACEs that apply to the object itself */
1024
1025         if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
1026                         (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY))
1027                 return -1;
1028         else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) &&
1029                         (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY))
1030                 return 1;
1031
1032         /* 2. ACEs that apply to a subobject of the object, such as
1033          * a property set or property. */
1034
1035         if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
1036                         !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
1037                 return -1;
1038         else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) &&
1039                         !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT)))
1040                 return 1;
1041
1042         return 0;
1043 }
1044
1045 /*******************************************************************
1046  Functions to convert a SEC_DESC ACE DACL list into canonical order.
1047  JRA.
1048
1049 --- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
1050
1051 The following describes the preferred order:
1052
1053  To ensure that noninherited ACEs have precedence over inherited ACEs,
1054  place all noninherited ACEs in a group before any inherited ACEs.
1055  This ordering ensures, for example, that a noninherited access-denied ACE
1056  is enforced regardless of any inherited ACE that allows access.
1057
1058  Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows:
1059         1. Access-denied ACEs that apply to the object itself
1060         2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property
1061         3. Access-allowed ACEs that apply to the object itself
1062         4. Access-allowed ACEs that apply to a subobject of the object"
1063
1064 ********************************************************************/
1065
1066 void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces)
1067 {
1068         unsigned int i;
1069
1070         if (!srclist || num_aces == 0)
1071                 return;
1072
1073         /* Sort so that non-inherited ACE's come first. */
1074         qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp);
1075
1076         /* Find the boundary between non-inherited ACEs. */
1077         for (i = 0; i < num_aces; i++ ) {
1078                 SEC_ACE *curr_ace = &srclist[i];
1079
1080                 if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE)
1081                         break;
1082         }
1083
1084         /* i now points at entry number of the first inherited ACE. */
1085
1086         /* Sort the non-inherited ACEs. */
1087         if (i)
1088                 qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
1089
1090         /* Now sort the inherited ACEs. */
1091         if (num_aces - i)
1092                 qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp);
1093 }