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