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