Sort entry points alphabetically.
[wine] / dlls / ntdll / sec.c
1 /*
2  *      Security functions
3  *
4  *      Copyright 1996-1998 Marcus Meissner
5  *      Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
34
35 #include "windef.h"
36 #include "wine/exception.h"
37 #include "ntdll_misc.h"
38 #include "excpt.h"
39 #include "wine/library.h"
40 #include "wine/debug.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
43
44 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
45
46 /* filter for page-fault exceptions */
47 static WINE_EXCEPTION_FILTER(page_fault)
48 {
49     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
50         return EXCEPTION_EXECUTE_HANDLER;
51     return EXCEPTION_CONTINUE_SEARCH;
52 }
53
54 /* helper function to copy an ACL */
55 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
56 {
57     DWORD size;
58
59     if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
60         return FALSE;
61         
62     size = ((ACL *)pSourceAcl)->AclSize;
63     if (nDestinationAclLength < size)
64         return FALSE;
65
66     memmove(pDestinationAcl, pSourceAcl, size);
67     return TRUE;
68 }
69
70 /*
71  *      SID FUNCTIONS
72  */
73
74 /******************************************************************************
75  *  RtlAllocateAndInitializeSid         [NTDLL.@]
76  *
77  */
78 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
79         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
80         BYTE nSubAuthorityCount,
81         DWORD nSubAuthority0, DWORD nSubAuthority1,
82         DWORD nSubAuthority2, DWORD nSubAuthority3,
83         DWORD nSubAuthority4, DWORD nSubAuthority5,
84         DWORD nSubAuthority6, DWORD nSubAuthority7,
85         PSID *pSid )
86 {
87
88         TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
89                 pIdentifierAuthority,nSubAuthorityCount,
90                 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
91                 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
92
93         if (!(*pSid = RtlAllocateHeap( GetProcessHeap(), 0,
94                                        RtlLengthRequiredSid(nSubAuthorityCount))))
95             return STATUS_NO_MEMORY;
96
97         ((SID*)*pSid)->Revision = SID_REVISION;
98
99         if (pIdentifierAuthority)
100           memcpy(&((SID*)*pSid)->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
101         *RtlSubAuthorityCountSid(*pSid) = nSubAuthorityCount;
102
103         if (nSubAuthorityCount > 0)
104           *RtlSubAuthoritySid(*pSid, 0) = nSubAuthority0;
105         if (nSubAuthorityCount > 1)
106           *RtlSubAuthoritySid(*pSid, 1) = nSubAuthority1;
107         if (nSubAuthorityCount > 2)
108           *RtlSubAuthoritySid(*pSid, 2) = nSubAuthority2;
109         if (nSubAuthorityCount > 3)
110           *RtlSubAuthoritySid(*pSid, 3) = nSubAuthority3;
111         if (nSubAuthorityCount > 4)
112           *RtlSubAuthoritySid(*pSid, 4) = nSubAuthority4;
113         if (nSubAuthorityCount > 5)
114           *RtlSubAuthoritySid(*pSid, 5) = nSubAuthority5;
115         if (nSubAuthorityCount > 6)
116           *RtlSubAuthoritySid(*pSid, 6) = nSubAuthority6;
117         if (nSubAuthorityCount > 7)
118           *RtlSubAuthoritySid(*pSid, 7) = nSubAuthority7;
119
120         return STATUS_SUCCESS;
121 }
122 /******************************************************************************
123  *  RtlEqualSid         [NTDLL.@]
124  *
125  * Determine if two SIDs are equal.
126  *
127  * PARAMS
128  *  pSid1 [I] Source SID
129  *  pSid2 [I] SID to compare with
130  *
131  * RETURNS
132  *  TRUE, if pSid1 is equal to pSid2,
133  *  FALSE otherwise.
134  */
135 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
136 {
137     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
138         return FALSE;
139
140     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
141         return FALSE;
142
143     if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
144         return FALSE;
145
146     return TRUE;
147 }
148
149 /******************************************************************************
150  * RtlEqualPrefixSid    [NTDLL.@]
151  */
152 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
153 {
154     if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
155         return FALSE;
156
157     if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
158         return FALSE;
159
160     if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
161         return FALSE;
162
163     return TRUE;
164 }
165
166
167 /******************************************************************************
168  *  RtlFreeSid          [NTDLL.@]
169  *
170  * Free the resources used by a SID.
171  *
172  * PARAMS
173  *  pSid [I] SID to Free.
174  *
175  * RETURNS
176  *  STATUS_SUCCESS.
177  */
178 DWORD WINAPI RtlFreeSid(PSID pSid)
179 {
180         TRACE("(%p)\n", pSid);
181         RtlFreeHeap( GetProcessHeap(), 0, pSid );
182         return STATUS_SUCCESS;
183 }
184
185 /**************************************************************************
186  * RtlLengthRequiredSid [NTDLL.@]
187  *
188  * Determine the amount of memory a SID will use
189  *
190  * PARAMS
191  *   nrofsubauths [I] Number of Sub Authorities in the SID.
192  *
193  * RETURNS
194  *   The size, in bytes, of a SID with nrofsubauths Sub Authorities.
195  */
196 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
197 {
198         return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
199 }
200
201 /**************************************************************************
202  *                 RtlLengthSid                         [NTDLL.@]
203  *
204  * Determine the amount of memory a SID is using
205  *
206  * PARAMS
207  *  pSid [I] SID to get the size of.
208  *
209  * RETURNS
210  *  The size, in bytes, of pSid.
211  */
212 DWORD WINAPI RtlLengthSid(PSID pSid)
213 {
214         TRACE("sid=%p\n",pSid);
215         if (!pSid) return 0;
216         return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
217 }
218
219 /**************************************************************************
220  *                 RtlInitializeSid                     [NTDLL.@]
221  *
222  * Initialise a SID.
223  *
224  * PARAMS
225  *  pSid                 [I] SID to initialise
226  *  pIdentifierAuthority [I] Identifier Authority
227  *  nSubAuthorityCount   [I] Number of Sub Authorities
228  *
229  * RETURNS
230  *  Success: TRUE. pSid is initialised with the details given.
231  *  Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
232  */
233 BOOL WINAPI RtlInitializeSid(
234         PSID pSid,
235         PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
236         BYTE nSubAuthorityCount)
237 {
238         int i;
239         SID* pisid=pSid;
240
241         if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
242           return FALSE;
243
244         pisid->Revision = SID_REVISION;
245         pisid->SubAuthorityCount = nSubAuthorityCount;
246         if (pIdentifierAuthority)
247           memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
248
249         for (i = 0; i < nSubAuthorityCount; i++)
250           *RtlSubAuthoritySid(pSid, i) = 0;
251
252         return TRUE;
253 }
254
255 /**************************************************************************
256  *                 RtlSubAuthoritySid                   [NTDLL.@]
257  *
258  * Return the Sub Authority of a SID
259  *
260  * PARAMS
261  *   pSid          [I] SID to get the Sub Authority from.
262  *   nSubAuthority [I] Sub Authority number.
263  *
264  * RETURNS
265  *   A pointer to The Sub Authority value of pSid.
266  */
267 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
268 {
269     return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
270 }
271
272 /**************************************************************************
273  * RtlIdentifierAuthoritySid    [NTDLL.@]
274  *
275  * Return the Identifier Authority of a SID.
276  *
277  * PARAMS
278  *   pSid [I] SID to get the Identifier Authority from.
279  *
280  * RETURNS
281  *   A pointer to the Identifier Authority value of pSid.
282  */
283 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
284 {
285     return &(((SID*)pSid)->IdentifierAuthority);
286 }
287
288 /**************************************************************************
289  *                 RtlSubAuthorityCountSid              [NTDLL.@]
290  *
291  * Get the number of Sub Authorities in a SID.
292  *
293  * PARAMS
294  *   pSid [I] SID to get the count from.
295  *
296  * RETURNS
297  *  A pointer to the Sub Authority count of pSid.
298  */
299 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
300 {
301     return &(((SID*)pSid)->SubAuthorityCount);
302 }
303
304 /**************************************************************************
305  *                 RtlCopySid                           [NTDLL.@]
306  */
307 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
308 {
309         if (!pSourceSid || !RtlValidSid(pSourceSid) ||
310             (nDestinationSidLength < RtlLengthSid(pSourceSid)))
311           return FALSE;
312
313         if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
314           return FALSE;
315
316         memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
317         return TRUE;
318 }
319 /******************************************************************************
320  * RtlValidSid [NTDLL.@]
321  *
322  * Determine if a SID is valid.
323  *
324  * PARAMS
325  *   pSid [I] SID to check
326  *
327  * RETURNS
328  *   TRUE if pSid is valid,
329  *   FALSE otherwise.
330  */
331 BOOLEAN WINAPI RtlValidSid( PSID pSid )
332 {
333     BOOL ret;
334     __TRY
335     {
336         ret = TRUE;
337         if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
338             ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
339         {
340             ret = FALSE;
341         }
342     }
343     __EXCEPT(page_fault)
344     {
345         WARN("(%p): invalid pointer!\n", pSid);
346         return FALSE;
347     }
348     __ENDTRY
349     return ret;
350 }
351
352
353 /*
354  *      security descriptor functions
355  */
356
357 /**************************************************************************
358  * RtlCreateSecurityDescriptor                  [NTDLL.@]
359  *
360  * Initialise a SECURITY_DESCRIPTOR.
361  *
362  * PARAMS
363  *  lpsd [O] Descriptor to initialise.
364  *  rev  [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
365  *
366  * RETURNS:
367  *  Success: STATUS_SUCCESS.
368  *  Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
369  */
370 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
371         PSECURITY_DESCRIPTOR lpsd,
372         DWORD rev)
373 {
374         if (rev!=SECURITY_DESCRIPTOR_REVISION)
375                 return STATUS_UNKNOWN_REVISION;
376         memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
377         ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
378         return STATUS_SUCCESS;
379 }
380
381 /**************************************************************************
382  * RtlCopySecurityDescriptor            [NTDLL.@]
383  *
384  * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
385  *
386  * PARAMS
387  *  pSourceSD      [O] SD to copy from.
388  *  pDestinationSD [I] Destination SD.
389  *
390  * RETURNS:
391  *  Success: STATUS_SUCCESS.
392  *  Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
393  */
394 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
395 {
396     SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
397     SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
398     PSID Owner, Group;
399     PACL Dacl, Sacl;
400     BOOLEAN defaulted, present;
401     DWORD length;
402     BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
403     
404     if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
405         return STATUS_UNKNOWN_REVISION;
406
407     /* copy initial data */
408     destSD->Revision = srcSD->Revision;
409     destSD->Sbz1 = srcSD->Sbz1;
410     destSD->Control = srcSD->Control;
411
412     /* copy Owner */
413     RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
414     length = RtlLengthSid(Owner);
415
416     if (isSelfRelative)
417     {
418         destSD->Owner = srcSD->Owner;
419         RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
420     }
421     else
422     {
423         destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
424         RtlCopySid(length, destSD->Owner, Owner);
425     }
426
427     /* copy Group */
428     RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
429     length = RtlLengthSid(Group);
430
431     if (isSelfRelative)
432     {
433         destSD->Group = srcSD->Group;
434         RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
435     }
436     else
437     {
438         destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
439         RtlCopySid(length, destSD->Group, Group);
440     }
441
442     /* copy Dacl */
443     if (srcSD->Control & SE_DACL_PRESENT)
444     {
445         RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
446         length = Dacl->AclSize;
447
448         if (isSelfRelative)
449         {
450             destSD->Dacl = srcSD->Dacl;
451             copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
452         }
453         else
454         {
455             destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
456             copy_acl(length, destSD->Dacl, Dacl);
457         }
458     }
459
460     /* copy Sacl */
461     if (srcSD->Control & SE_SACL_PRESENT)
462     {
463         RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
464         length = Sacl->AclSize;
465
466         if (isSelfRelative)
467         {
468             destSD->Sacl = srcSD->Sacl;
469             copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
470         }
471         else
472         {
473             destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
474             copy_acl(length, destSD->Sacl, Sacl);
475         }
476     }
477
478     return STATUS_SUCCESS;
479 }
480
481 /**************************************************************************
482  * RtlValidSecurityDescriptor                   [NTDLL.@]
483  *
484  * Determine if a SECURITY_DESCRIPTOR is valid.
485  *
486  * PARAMS
487  *  SecurityDescriptor [I] Descriptor to check.
488  *
489  * RETURNS
490  *   Success: STATUS_SUCCESS.
491  *   Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
492  */
493 NTSTATUS WINAPI RtlValidSecurityDescriptor(
494         PSECURITY_DESCRIPTOR SecurityDescriptor)
495 {
496         if ( ! SecurityDescriptor )
497                 return STATUS_INVALID_SECURITY_DESCR;
498         if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
499                 return STATUS_UNKNOWN_REVISION;
500
501         return STATUS_SUCCESS;
502 }
503
504 /**************************************************************************
505  *  RtlLengthSecurityDescriptor                 [NTDLL.@]
506  */
507 ULONG WINAPI RtlLengthSecurityDescriptor(
508         PSECURITY_DESCRIPTOR pSecurityDescriptor)
509 {
510         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
511         ULONG offset = 0;
512         ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
513
514         if ( lpsd == NULL )
515                 return 0;
516
517         if ( lpsd->Control & SE_SELF_RELATIVE)
518                 offset = (ULONG) lpsd;
519
520         if ( lpsd->Owner != NULL )
521                 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
522
523         if ( lpsd->Group != NULL )
524                 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
525
526         if ( (lpsd->Control & SE_SACL_PRESENT) &&
527               lpsd->Sacl != NULL )
528                 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
529
530         if ( (lpsd->Control & SE_DACL_PRESENT) &&
531               lpsd->Dacl != NULL )
532                 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
533
534         return Size;
535 }
536
537 /******************************************************************************
538  *  RtlGetDaclSecurityDescriptor                [NTDLL.@]
539  *
540  */
541 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
542         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
543         OUT PBOOLEAN lpbDaclPresent,
544         OUT PACL *pDacl,
545         OUT PBOOLEAN lpbDaclDefaulted)
546 {
547         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
548
549         TRACE("(%p,%p,%p,%p)\n",
550         pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
551
552         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
553           return STATUS_UNKNOWN_REVISION ;
554
555         if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
556         {
557           if ( SE_SELF_RELATIVE & lpsd->Control)
558             *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
559           else
560             *pDacl = lpsd->Dacl;
561
562           *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
563         }
564
565         return STATUS_SUCCESS;
566 }
567
568 /**************************************************************************
569  *  RtlSetDaclSecurityDescriptor                [NTDLL.@]
570  */
571 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
572         PSECURITY_DESCRIPTOR pSecurityDescriptor,
573         BOOLEAN daclpresent,
574         PACL dacl,
575         BOOLEAN dacldefaulted )
576 {
577         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
578
579         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
580                 return STATUS_UNKNOWN_REVISION;
581         if (lpsd->Control & SE_SELF_RELATIVE)
582                 return STATUS_INVALID_SECURITY_DESCR;
583
584         if (!daclpresent)
585         {       lpsd->Control &= ~SE_DACL_PRESENT;
586                 return TRUE;
587         }
588
589         lpsd->Control |= SE_DACL_PRESENT;
590         lpsd->Dacl = dacl;
591
592         if (dacldefaulted)
593                 lpsd->Control |= SE_DACL_DEFAULTED;
594         else
595                 lpsd->Control &= ~SE_DACL_DEFAULTED;
596
597         return STATUS_SUCCESS;
598 }
599
600 /******************************************************************************
601  *  RtlGetSaclSecurityDescriptor                [NTDLL.@]
602  *
603  */
604 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
605         IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
606         OUT PBOOLEAN lpbSaclPresent,
607         OUT PACL *pSacl,
608         OUT PBOOLEAN lpbSaclDefaulted)
609 {
610         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
611
612         TRACE("(%p,%p,%p,%p)\n",
613         pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
614
615         if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
616           return STATUS_UNKNOWN_REVISION;
617
618         if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
619         {
620           if (SE_SELF_RELATIVE & lpsd->Control)
621             *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
622           else
623             *pSacl = lpsd->Sacl;
624
625           *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
626         }
627
628         return STATUS_SUCCESS;
629 }
630
631 /**************************************************************************
632  * RtlSetSaclSecurityDescriptor                 [NTDLL.@]
633  */
634 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
635         PSECURITY_DESCRIPTOR pSecurityDescriptor,
636         BOOLEAN saclpresent,
637         PACL sacl,
638         BOOLEAN sacldefaulted)
639 {
640         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
641
642         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
643                 return STATUS_UNKNOWN_REVISION;
644         if (lpsd->Control & SE_SELF_RELATIVE)
645                 return STATUS_INVALID_SECURITY_DESCR;
646         if (!saclpresent) {
647                 lpsd->Control &= ~SE_SACL_PRESENT;
648                 return 0;
649         }
650         lpsd->Control |= SE_SACL_PRESENT;
651         lpsd->Sacl = sacl;
652         if (sacldefaulted)
653                 lpsd->Control |= SE_SACL_DEFAULTED;
654         else
655                 lpsd->Control &= ~SE_SACL_DEFAULTED;
656         return STATUS_SUCCESS;
657 }
658
659 /**************************************************************************
660  * RtlGetOwnerSecurityDescriptor                [NTDLL.@]
661  */
662 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
663         PSECURITY_DESCRIPTOR pSecurityDescriptor,
664         PSID *Owner,
665         PBOOLEAN OwnerDefaulted)
666 {
667         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
668
669         if ( !lpsd  || !Owner || !OwnerDefaulted )
670                 return STATUS_INVALID_PARAMETER;
671
672         if (lpsd->Owner != NULL)
673         {
674             if (lpsd->Control & SE_SELF_RELATIVE)
675                 *Owner = (PSID)((LPBYTE)lpsd +
676                                 (ULONG)lpsd->Owner);
677             else
678                 *Owner = lpsd->Owner;
679
680             if ( lpsd->Control & SE_OWNER_DEFAULTED )
681                 *OwnerDefaulted = TRUE;
682             else
683                 *OwnerDefaulted = FALSE;
684         }
685         else
686             *Owner = NULL;
687
688         return STATUS_SUCCESS;
689 }
690
691 /**************************************************************************
692  *                 RtlSetOwnerSecurityDescriptor                [NTDLL.@]
693  */
694 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
695         PSECURITY_DESCRIPTOR pSecurityDescriptor,
696         PSID owner,
697         BOOLEAN ownerdefaulted)
698 {
699         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
700
701         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
702                 return STATUS_UNKNOWN_REVISION;
703         if (lpsd->Control & SE_SELF_RELATIVE)
704                 return STATUS_INVALID_SECURITY_DESCR;
705
706         lpsd->Owner = owner;
707         if (ownerdefaulted)
708                 lpsd->Control |= SE_OWNER_DEFAULTED;
709         else
710                 lpsd->Control &= ~SE_OWNER_DEFAULTED;
711         return STATUS_SUCCESS;
712 }
713
714 /**************************************************************************
715  *                 RtlSetGroupSecurityDescriptor                [NTDLL.@]
716  */
717 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
718         PSECURITY_DESCRIPTOR pSecurityDescriptor,
719         PSID group,
720         BOOLEAN groupdefaulted)
721 {
722         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
723
724         if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
725                 return STATUS_UNKNOWN_REVISION;
726         if (lpsd->Control & SE_SELF_RELATIVE)
727                 return STATUS_INVALID_SECURITY_DESCR;
728
729         lpsd->Group = group;
730         if (groupdefaulted)
731                 lpsd->Control |= SE_GROUP_DEFAULTED;
732         else
733                 lpsd->Control &= ~SE_GROUP_DEFAULTED;
734         return STATUS_SUCCESS;
735 }
736
737 /**************************************************************************
738  *                 RtlGetGroupSecurityDescriptor                [NTDLL.@]
739  */
740 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
741         PSECURITY_DESCRIPTOR pSecurityDescriptor,
742         PSID *Group,
743         PBOOLEAN GroupDefaulted)
744 {
745         SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
746
747         if ( !lpsd || !Group || !GroupDefaulted )
748                 return STATUS_INVALID_PARAMETER;
749
750         if (lpsd->Group != NULL)
751         {
752             if (lpsd->Control & SE_SELF_RELATIVE)
753                 *Group = (PSID)((LPBYTE)lpsd +
754                                 (ULONG)lpsd->Group);
755             else
756                 *Group = lpsd->Group;
757
758             if ( lpsd->Control & SE_GROUP_DEFAULTED )
759                 *GroupDefaulted = TRUE;
760             else
761                 *GroupDefaulted = FALSE;
762         }
763         else
764             *Group = NULL;
765
766         return STATUS_SUCCESS;
767 }
768
769 /**************************************************************************
770  *                 RtlMakeSelfRelativeSD                [NTDLL.@]
771  */
772 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
773         IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
774         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
775         IN OUT LPDWORD lpdwBufferLength)
776 {
777     ULONG offsetRel;
778     ULONG length;
779     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
780     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
781
782     TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
783         lpdwBufferLength ? *lpdwBufferLength: -1);
784
785     if (!lpdwBufferLength || !pAbs)
786         return STATUS_INVALID_PARAMETER;
787
788     length = RtlLengthSecurityDescriptor(pAbs);
789     if (*lpdwBufferLength < length)
790     {
791         *lpdwBufferLength = length;
792         return STATUS_BUFFER_TOO_SMALL;
793     }
794
795     if (!pRel)
796         return STATUS_INVALID_PARAMETER;
797
798     if (pAbs->Control & SE_SELF_RELATIVE)
799     {
800         memcpy(pRel, pAbs, length);
801         return STATUS_SUCCESS;
802     }
803
804     pRel->Revision = pAbs->Revision;
805     pRel->Sbz1 = pAbs->Sbz1;
806     pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
807
808     offsetRel = sizeof(SECURITY_DESCRIPTOR);
809     pRel->Owner = (PSID) offsetRel;
810     length = RtlLengthSid(pAbs->Owner);
811     memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
812
813     offsetRel += length;
814     pRel->Group = (PSID) offsetRel;
815     length = RtlLengthSid(pAbs->Group);
816     memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
817
818     if (pRel->Control & SE_SACL_PRESENT)
819     {
820         offsetRel += length;
821         pRel->Sacl = (PACL) offsetRel;
822         length = pAbs->Sacl->AclSize;
823         memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
824     }
825     else
826     {
827         pRel->Sacl = NULL;
828     }
829
830     if (pRel->Control & SE_DACL_PRESENT)
831     {
832         offsetRel += length;
833         pRel->Dacl = (PACL) offsetRel;
834         length = pAbs->Dacl->AclSize;
835         memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
836     }
837     else
838     {
839         pRel->Dacl = NULL;
840     }
841
842     return STATUS_SUCCESS;
843 }
844
845
846 /**************************************************************************
847  *                 RtlSelfRelativeToAbsoluteSD [NTDLL.@]
848  */
849 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
850         IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
851         OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
852         OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
853         OUT PACL pDacl,
854         OUT LPDWORD lpdwDaclSize,
855         OUT PACL pSacl,
856         OUT LPDWORD lpdwSaclSize,
857         OUT PSID pOwner,
858         OUT LPDWORD lpdwOwnerSize,
859         OUT PSID pPrimaryGroup,
860         OUT LPDWORD lpdwPrimaryGroupSize)
861 {
862     NTSTATUS status = STATUS_SUCCESS;
863     SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
864     SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
865
866     if (!pRel ||
867         !lpdwAbsoluteSecurityDescriptorSize ||
868         !lpdwDaclSize ||
869         !lpdwSaclSize ||
870         !lpdwOwnerSize ||
871         !lpdwPrimaryGroupSize ||
872         ~pRel->Control & SE_SELF_RELATIVE)
873         return STATUS_INVALID_PARAMETER;
874
875     /* Confirm buffers are sufficiently large */
876     if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
877     {
878         *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
879         status = STATUS_BUFFER_TOO_SMALL;
880     }
881
882     if (pRel->Control & SE_DACL_PRESENT &&
883         *lpdwDaclSize  < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
884     {
885         *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
886         status = STATUS_BUFFER_TOO_SMALL;
887     }
888
889     if (pRel->Control & SE_SACL_PRESENT &&
890         *lpdwSaclSize  < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
891     {
892         *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
893         status = STATUS_BUFFER_TOO_SMALL;
894     }
895
896     if (pRel->Owner &&
897         *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
898     {
899         *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
900         status = STATUS_BUFFER_TOO_SMALL;
901     }
902
903     if (pRel->Group &&
904         *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
905     {
906         *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
907         status = STATUS_BUFFER_TOO_SMALL;
908     }
909
910     if (status != STATUS_SUCCESS)
911         return status;
912
913     /* Copy structures */
914     pAbs->Revision = pRel->Revision;
915     pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
916
917     if (pRel->Control & SE_SACL_PRESENT)
918     {
919         PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
920
921         memcpy(pSacl, pAcl, pAcl->AclSize);
922         pAbs->Sacl = pSacl;
923     }
924
925     if (pRel->Control & SE_DACL_PRESENT)
926     {
927         PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
928         memcpy(pDacl, pAcl, pAcl->AclSize);
929         pAbs->Dacl = pDacl;
930     }
931
932     if (pRel->Owner)
933     {
934         PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
935         memcpy(pOwner, psid, RtlLengthSid(psid));
936         pAbs->Owner = pOwner;
937     }
938
939     if (pRel->Group)
940     {
941         PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
942         memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
943         pAbs->Group = pPrimaryGroup;
944     }
945
946     return status;
947 }
948
949 /******************************************************************************
950  * RtlGetControlSecurityDescriptor (NTDLL.@)
951  */
952 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
953     PSECURITY_DESCRIPTOR pSecurityDescriptor,
954     PSECURITY_DESCRIPTOR_CONTROL pControl,
955     LPDWORD lpdwRevision)
956 {
957     SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
958
959     TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
960
961     *lpdwRevision = lpsd->Revision;
962
963     if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
964         return STATUS_UNKNOWN_REVISION;
965
966     *pControl = lpsd->Control;
967
968     return STATUS_SUCCESS;
969 }
970
971
972 /**************************************************************************
973  *                 RtlAbsoluteToSelfRelativeSD [NTDLL.@]
974  */
975 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
976     PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
977     PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
978     PULONG BufferLength)
979 {
980     SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
981
982     TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
983           SelfRelativeSecurityDescriptor, BufferLength);
984
985     if (abs->Control & SE_SELF_RELATIVE)
986         return STATUS_BAD_DESCRIPTOR_FORMAT;
987
988     return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor, 
989         SelfRelativeSecurityDescriptor, BufferLength);
990 }
991
992
993 /*
994  *      access control list's
995  */
996
997 /**************************************************************************
998  *                 RtlCreateAcl                         [NTDLL.@]
999  *
1000  * NOTES
1001  *    This should return NTSTATUS
1002  */
1003 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1004 {
1005         TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
1006
1007         if (rev!=ACL_REVISION)
1008                 return STATUS_INVALID_PARAMETER;
1009         if (size<sizeof(ACL))
1010                 return STATUS_BUFFER_TOO_SMALL;
1011         if (size>0xFFFF)
1012                 return STATUS_INVALID_PARAMETER;
1013
1014         memset(acl,'\0',sizeof(ACL));
1015         acl->AclRevision        = rev;
1016         acl->AclSize            = size;
1017         acl->AceCount           = 0;
1018         return STATUS_SUCCESS;
1019 }
1020
1021 /**************************************************************************
1022  *                 RtlFirstFreeAce                      [NTDLL.@]
1023  * looks for the AceCount+1 ACE, and if it is still within the alloced
1024  * ACL, return a pointer to it
1025  */
1026 BOOLEAN WINAPI RtlFirstFreeAce(
1027         PACL acl,
1028         PACE_HEADER *x)
1029 {
1030         PACE_HEADER     ace;
1031         int             i;
1032
1033         *x = 0;
1034         ace = (PACE_HEADER)(acl+1);
1035         for (i=0;i<acl->AceCount;i++) {
1036                 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
1037                         return 0;
1038                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1039         }
1040         if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
1041                 return 0;
1042         *x = ace;
1043         return 1;
1044 }
1045
1046 /**************************************************************************
1047  *                 RtlAddAce                            [NTDLL.@]
1048  */
1049 NTSTATUS WINAPI RtlAddAce(
1050         PACL acl,
1051         DWORD rev,
1052         DWORD xnrofaces,
1053         PACE_HEADER acestart,
1054         DWORD acelen)
1055 {
1056         PACE_HEADER     ace,targetace;
1057         int             nrofaces;
1058
1059         if (acl->AclRevision != ACL_REVISION)
1060                 return STATUS_INVALID_PARAMETER;
1061         if (!RtlFirstFreeAce(acl,&targetace))
1062                 return STATUS_INVALID_PARAMETER;
1063         nrofaces=0;ace=acestart;
1064         while (((DWORD)ace-(DWORD)acestart)<acelen) {
1065                 nrofaces++;
1066                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1067         }
1068         if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
1069                 return STATUS_INVALID_PARAMETER;
1070         memcpy((LPBYTE)targetace,acestart,acelen);
1071         acl->AceCount+=nrofaces;
1072         return STATUS_SUCCESS;
1073 }
1074
1075 /**************************************************************************
1076  *                 RtlDeleteAce                         [NTDLL.@]
1077  */
1078 NTSTATUS  WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1079 {
1080         NTSTATUS status;
1081         PACE_HEADER pAce;
1082
1083         status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1084
1085         if (STATUS_SUCCESS == status)
1086         {
1087                 PACE_HEADER pcAce;
1088                 DWORD len = 0;
1089
1090                 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1091                 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1092                 {
1093                         len += pcAce->AceSize;
1094                         pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1095                 }
1096
1097                 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1098                 pAcl->AceCount--;
1099         }
1100
1101         TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
1102
1103         return status;
1104 }
1105
1106 /******************************************************************************
1107  *  RtlAddAccessAllowedAce              [NTDLL.@]
1108  */
1109 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1110         IN OUT PACL pAcl,
1111         IN DWORD dwAceRevision,
1112         IN DWORD AccessMask,
1113         IN PSID pSid)
1114 {
1115         return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1116 }
1117  
1118 /******************************************************************************
1119  *  RtlAddAccessAllowedAceEx            [NTDLL.@]
1120  */
1121 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1122         IN OUT PACL pAcl,
1123         IN DWORD dwAceRevision,
1124         IN DWORD AceFlags,
1125         IN DWORD AccessMask,
1126         IN PSID pSid)
1127 {
1128         DWORD dwLengthSid;
1129         ACCESS_ALLOWED_ACE * pAaAce;
1130         DWORD dwSpaceLeft;
1131
1132         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1133                 pAcl, dwAceRevision, AccessMask, pSid);
1134
1135         if (!RtlValidSid(pSid))
1136                 return STATUS_INVALID_SID;
1137         if (!RtlValidAcl(pAcl))
1138                 return STATUS_INVALID_ACL;
1139
1140         dwLengthSid = RtlLengthSid(pSid);
1141         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
1142                 return STATUS_INVALID_ACL;
1143
1144         if (!pAaAce)
1145                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1146
1147         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
1148         if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
1149                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1150
1151         pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1152         pAaAce->Header.AceFlags = AceFlags;
1153         pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
1154         pAaAce->Mask = AccessMask;
1155         pAcl->AceCount++;
1156         RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1157         return STATUS_SUCCESS;
1158 }
1159
1160 /******************************************************************************
1161  *  RtlAddAccessDeniedAce               [NTDLL.@]
1162  */
1163 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1164         IN OUT PACL pAcl,
1165         IN DWORD dwAceRevision,
1166         IN DWORD AccessMask,
1167         IN PSID pSid)
1168 {
1169         return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1170 }
1171
1172 /******************************************************************************
1173  *  RtlAddAccessDeniedAceEx             [NTDLL.@]
1174  */
1175 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1176         IN OUT PACL pAcl,
1177         IN DWORD dwAceRevision,
1178         IN DWORD AceFlags,
1179         IN DWORD AccessMask,
1180         IN PSID pSid)
1181 {
1182         DWORD dwLengthSid;
1183         DWORD dwSpaceLeft;
1184         ACCESS_DENIED_ACE * pAdAce;
1185
1186         TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1187                 pAcl, dwAceRevision, AccessMask, pSid);
1188
1189         if (!RtlValidSid(pSid))
1190                 return STATUS_INVALID_SID;
1191         if (!RtlValidAcl(pAcl))
1192                 return STATUS_INVALID_ACL;
1193
1194         dwLengthSid = RtlLengthSid(pSid);
1195         if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1196                 return STATUS_INVALID_ACL;
1197
1198         if (!pAdAce)
1199                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1200
1201         dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1202         if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1203                 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1204
1205         pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1206         pAdAce->Header.AceFlags = AceFlags;
1207         pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1208         pAdAce->Mask = AccessMask;
1209         pAcl->AceCount++;
1210         RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1211         return STATUS_SUCCESS;
1212 }
1213
1214 /******************************************************************************
1215  *  RtlValidAcl         [NTDLL.@]
1216  */
1217 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1218 {
1219         BOOLEAN ret;
1220         TRACE("(%p)\n", pAcl);
1221
1222         __TRY
1223         {
1224                 PACE_HEADER     ace;
1225                 int             i;
1226
1227                 if (pAcl->AclRevision != ACL_REVISION)
1228                     ret = FALSE;
1229                 else
1230                 {
1231                     ace = (PACE_HEADER)(pAcl+1);
1232                     ret = TRUE;
1233                     for (i=0;i<=pAcl->AceCount;i++)
1234                     {
1235                         if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1236                         {
1237                             ret = FALSE;
1238                             break;
1239                         }
1240                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1241                     }
1242                 }
1243         }
1244         __EXCEPT(page_fault)
1245         {
1246                 WARN("(%p): invalid pointer!\n", pAcl);
1247                 return 0;
1248         }
1249         __ENDTRY
1250         return ret;
1251 }
1252
1253 /******************************************************************************
1254  *  RtlGetAce           [NTDLL.@]
1255  */
1256 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1257 {
1258         PACE_HEADER ace;
1259
1260         TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1261
1262         if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1263                 return STATUS_INVALID_PARAMETER;
1264
1265         ace = (PACE_HEADER)(pAcl + 1);
1266         for (;dwAceIndex;dwAceIndex--)
1267                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1268
1269         *pAce = (LPVOID) ace;
1270
1271         return STATUS_SUCCESS;
1272 }
1273
1274 /*
1275  *      misc
1276  */
1277
1278 /******************************************************************************
1279  *  RtlAdjustPrivilege          [NTDLL.@]
1280  *
1281  * Enables or disables a privilege from the calling thread or process.
1282  *
1283  * PARAMS
1284  *  Privilege     [I] Privilege index to change.
1285  *  Enable        [I] If TRUE, then enable the privilege otherwise disable.
1286  *  CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1287  *  Enabled       [O] Whether privilege was previously enabled or disabled.
1288  *
1289  * RETURNS
1290  *  Success: STATUS_SUCCESS.
1291  *  Failure: NTSTATUS code.
1292  *
1293  * SEE ALSO
1294  *  NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1295  *
1296  */
1297 NTSTATUS WINAPI
1298 RtlAdjustPrivilege(ULONG Privilege,
1299                    BOOLEAN Enable,
1300                    BOOLEAN CurrentThread,
1301                    PBOOLEAN Enabled)
1302 {
1303     TOKEN_PRIVILEGES NewState;
1304     TOKEN_PRIVILEGES OldState;
1305     ULONG ReturnLength;
1306     HANDLE TokenHandle;
1307     NTSTATUS Status;
1308
1309     TRACE("(%ld, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1310         CurrentThread ? "TRUE" : "FALSE", Enabled);
1311
1312     if (CurrentThread)
1313     {
1314         Status = NtOpenThreadToken(GetCurrentThread(),
1315                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1316                                    FALSE,
1317                                    &TokenHandle);
1318     }
1319     else
1320     {
1321         Status = NtOpenProcessToken(GetCurrentProcess(),
1322                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1323                                     &TokenHandle);
1324     }
1325
1326     if (!NT_SUCCESS(Status))
1327     {
1328         WARN("Retrieving token handle failed (Status %lx)\n", Status);
1329         return Status;
1330     }
1331
1332     OldState.PrivilegeCount = 1;
1333
1334     NewState.PrivilegeCount = 1;
1335     NewState.Privileges[0].Luid.LowPart = Privilege;
1336     NewState.Privileges[0].Luid.HighPart = 0;
1337     NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1338
1339     Status = NtAdjustPrivilegesToken(TokenHandle,
1340                                      FALSE,
1341                                      &NewState,
1342                                      sizeof(TOKEN_PRIVILEGES),
1343                                      &OldState,
1344                                      &ReturnLength);
1345     NtClose (TokenHandle);
1346     if (Status == STATUS_NOT_ALL_ASSIGNED)
1347     {
1348         TRACE("Failed to assign all privileges\n");
1349         return STATUS_PRIVILEGE_NOT_HELD;
1350     }
1351     if (!NT_SUCCESS(Status))
1352     {
1353         WARN("NtAdjustPrivilegesToken() failed (Status %lx)\n", Status);
1354         return Status;
1355     }
1356
1357     if (OldState.PrivilegeCount == 0)
1358         *Enabled = Enable;
1359     else
1360         *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1361
1362     return STATUS_SUCCESS;
1363 }
1364
1365 /******************************************************************************
1366  *  RtlImpersonateSelf          [NTDLL.@]
1367  *
1368  * Makes an impersonation token that represents the process user and assigns
1369  * to the current thread.
1370  *
1371  * PARAMS
1372  *  ImpersonationLevel [I] Level at which to impersonate.
1373  *
1374  * RETURNS
1375  *  Success: STATUS_SUCCESS.
1376  *  Failure: NTSTATUS code.
1377  */
1378 NTSTATUS WINAPI
1379 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1380 {
1381     NTSTATUS Status;
1382     OBJECT_ATTRIBUTES ObjectAttributes;
1383     HANDLE ProcessToken;
1384     HANDLE ImpersonationToken;
1385
1386     TRACE("(%08x)\n", ImpersonationLevel);
1387
1388     Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1389                                  &ProcessToken);
1390     if (Status != STATUS_SUCCESS)
1391         return Status;
1392
1393     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1394
1395     Status = NtDuplicateToken( ProcessToken,
1396                                TOKEN_IMPERSONATE,
1397                                &ObjectAttributes,
1398                                ImpersonationLevel,
1399                                TokenImpersonation,
1400                                &ImpersonationToken );
1401     if (Status != STATUS_SUCCESS)
1402     {
1403         NtClose( ProcessToken );
1404         return Status;
1405     }
1406
1407     Status = NtSetInformationThread( GetCurrentThread(),
1408                                      ThreadImpersonationToken,
1409                                      &ImpersonationToken,
1410                                      sizeof(ImpersonationToken) );
1411
1412     NtClose( ImpersonationToken );
1413     NtClose( ProcessToken );
1414
1415     return Status;
1416 }
1417
1418 /******************************************************************************
1419  *  NtAccessCheck               [NTDLL.@]
1420  *  ZwAccessCheck               [NTDLL.@]
1421  *
1422  * Checks that a user represented by a token is allowed to access an object
1423  * represented by a security descriptor.
1424  *
1425  * PARAMS
1426  *  SecurityDescriptor [I] The security descriptor of the object to check.
1427  *  ClientToken        [I] Token of the user accessing the object.
1428  *  DesiredAccess      [I] The desired access to the object.
1429  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1430  *  PrivilegeSet       [I/O] Privileges used during the access check.
1431  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1432  *  GrantedAccess      [O] The actual access rights granted.
1433  *  AccessStatus       [O] The status of the access check.
1434  *
1435  * RETURNS
1436  *  NTSTATUS code.
1437  *
1438  * NOTES
1439  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1440  *  the maximum access rights allowed by the SD and returns them in
1441  *  GrantedAccess.
1442  *  The SecurityDescriptor must have a valid owner and groups present,
1443  *  otherwise the function will fail.
1444  */
1445 NTSTATUS WINAPI
1446 NtAccessCheck(
1447     PSECURITY_DESCRIPTOR SecurityDescriptor,
1448     HANDLE ClientToken,
1449     ACCESS_MASK DesiredAccess,
1450     PGENERIC_MAPPING GenericMapping,
1451     PPRIVILEGE_SET PrivilegeSet,
1452     PULONG ReturnLength,
1453     PULONG GrantedAccess,
1454     NTSTATUS *AccessStatus)
1455 {
1456     NTSTATUS status;
1457
1458     TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1459         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1460         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1461
1462     SERVER_START_REQ( access_check )
1463     {
1464         struct security_descriptor sd;
1465         PSID owner;
1466         PSID group;
1467         PACL sacl;
1468         PACL dacl;
1469         BOOLEAN defaulted, present;
1470         DWORD revision;
1471         SECURITY_DESCRIPTOR_CONTROL control;
1472
1473         req->handle = ClientToken;
1474         req->desired_access = DesiredAccess;
1475         req->mapping_read = GenericMapping->GenericRead;
1476         req->mapping_write = GenericMapping->GenericWrite;
1477         req->mapping_execute = GenericMapping->GenericExecute;
1478         req->mapping_all = GenericMapping->GenericAll;
1479
1480         /* marshal security descriptor */
1481         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1482         sd.control = control & ~SE_SELF_RELATIVE;
1483         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1484         sd.owner_len = RtlLengthSid( owner );
1485         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1486         sd.group_len = RtlLengthSid( group );
1487         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1488         sd.sacl_len = (present ? sacl->AclSize : 0);
1489         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1490         sd.dacl_len = (present ? dacl->AclSize : 0);
1491
1492         wine_server_add_data( req, &sd, sizeof(sd) );
1493         wine_server_add_data( req, owner, sd.owner_len );
1494         wine_server_add_data( req, group, sd.group_len );
1495         wine_server_add_data( req, sacl, sd.sacl_len );
1496         wine_server_add_data( req, dacl, sd.dacl_len );
1497
1498         wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1499
1500         status = wine_server_call( req );
1501
1502         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1503         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1504
1505         if (status == STATUS_SUCCESS)
1506             *AccessStatus = reply->access_status;
1507         *GrantedAccess = reply->access_granted;
1508     }
1509     SERVER_END_REQ;
1510
1511     return status;
1512 }
1513
1514 /******************************************************************************
1515  *  NtSetSecurityObject         [NTDLL.@]
1516  */
1517 NTSTATUS WINAPI
1518 NtSetSecurityObject(
1519         IN HANDLE Handle,
1520         IN SECURITY_INFORMATION SecurityInformation,
1521         IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1522 {
1523         FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1524         return STATUS_SUCCESS;
1525 }
1526
1527 /******************************************************************************
1528  * RtlConvertSidToUnicodeString (NTDLL.@)
1529  *
1530  * The returned SID is used to access the USER registry hive usually
1531  *
1532  * the native function returns something like
1533  * "S-1-5-21-0000000000-000000000-0000000000-500";
1534  */
1535 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1536        PUNICODE_STRING String,
1537        PSID Sid,
1538        BOOLEAN AllocateString)
1539 {
1540     const char *user = wine_get_user_name();
1541     int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1542
1543     FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1544
1545     String->Length = len - sizeof(WCHAR);
1546     if (AllocateString)
1547     {
1548         String->MaximumLength = len;
1549         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1550             return STATUS_NO_MEMORY;
1551     }
1552     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1553
1554     ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1555     return STATUS_SUCCESS;
1556 }
1557
1558 /******************************************************************************
1559  * RtlQueryInformationAcl (NTDLL.@)
1560  */
1561 NTSTATUS WINAPI RtlQueryInformationAcl(
1562     PACL pAcl,
1563     LPVOID pAclInformation,
1564     DWORD nAclInformationLength,
1565     ACL_INFORMATION_CLASS dwAclInformationClass)
1566 {
1567     NTSTATUS status = STATUS_SUCCESS;
1568
1569     TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n", 
1570         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1571
1572     switch (dwAclInformationClass)
1573     {
1574         case AclRevisionInformation:
1575         {
1576             PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1577
1578             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1579                 status = STATUS_INVALID_PARAMETER;
1580             else
1581                 paclrev->AclRevision = pAcl->AclRevision;
1582
1583             break;
1584         }
1585
1586         case AclSizeInformation:
1587         {
1588             PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1589
1590             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1591                 status = STATUS_INVALID_PARAMETER;
1592             else
1593             {
1594                 INT i;
1595                 PACE_HEADER ace;
1596
1597                 paclsize->AceCount = pAcl->AceCount;
1598
1599                 paclsize->AclBytesInUse = 0;
1600                 ace = (PACE_HEADER) (pAcl + 1);
1601
1602                 for (i = 0; i < pAcl->AceCount; i++)
1603                 {
1604                     paclsize->AclBytesInUse += ace->AceSize;
1605                     ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1606                 }
1607
1608                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1609                 {
1610                     WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1611                     paclsize->AclBytesFree = 0;
1612                     paclsize->AclBytesInUse = pAcl->AclSize;
1613                 }
1614                 else
1615                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1616             }
1617
1618             break;
1619         }
1620
1621         default:
1622             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1623             status = STATUS_INVALID_PARAMETER;
1624     }
1625
1626     return status;
1627 }