server: Extend get_token_user server call to also retrieve SIDs for the token's owner...
[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                         ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1332                     }
1333                 }
1334         }
1335         __EXCEPT_PAGE_FAULT
1336         {
1337                 WARN("(%p): invalid pointer!\n", pAcl);
1338                 return 0;
1339         }
1340         __ENDTRY
1341         return ret;
1342 }
1343
1344 /******************************************************************************
1345  *  RtlGetAce           [NTDLL.@]
1346  */
1347 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1348 {
1349         PACE_HEADER ace;
1350
1351         TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1352
1353         if (dwAceIndex >= pAcl->AceCount)
1354                 return STATUS_INVALID_PARAMETER;
1355
1356         ace = (PACE_HEADER)(pAcl + 1);
1357         for (;dwAceIndex;dwAceIndex--)
1358                 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1359
1360         *pAce = ace;
1361
1362         return STATUS_SUCCESS;
1363 }
1364
1365 /*
1366  *      misc
1367  */
1368
1369 /******************************************************************************
1370  *  RtlAdjustPrivilege          [NTDLL.@]
1371  *
1372  * Enables or disables a privilege from the calling thread or process.
1373  *
1374  * PARAMS
1375  *  Privilege     [I] Privilege index to change.
1376  *  Enable        [I] If TRUE, then enable the privilege otherwise disable.
1377  *  CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1378  *  Enabled       [O] Whether privilege was previously enabled or disabled.
1379  *
1380  * RETURNS
1381  *  Success: STATUS_SUCCESS.
1382  *  Failure: NTSTATUS code.
1383  *
1384  * SEE ALSO
1385  *  NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1386  *
1387  */
1388 NTSTATUS WINAPI
1389 RtlAdjustPrivilege(ULONG Privilege,
1390                    BOOLEAN Enable,
1391                    BOOLEAN CurrentThread,
1392                    PBOOLEAN Enabled)
1393 {
1394     TOKEN_PRIVILEGES NewState;
1395     TOKEN_PRIVILEGES OldState;
1396     ULONG ReturnLength;
1397     HANDLE TokenHandle;
1398     NTSTATUS Status;
1399
1400     TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1401         CurrentThread ? "TRUE" : "FALSE", Enabled);
1402
1403     if (CurrentThread)
1404     {
1405         Status = NtOpenThreadToken(GetCurrentThread(),
1406                                    TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1407                                    FALSE,
1408                                    &TokenHandle);
1409     }
1410     else
1411     {
1412         Status = NtOpenProcessToken(GetCurrentProcess(),
1413                                     TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1414                                     &TokenHandle);
1415     }
1416
1417     if (!NT_SUCCESS(Status))
1418     {
1419         WARN("Retrieving token handle failed (Status %x)\n", Status);
1420         return Status;
1421     }
1422
1423     OldState.PrivilegeCount = 1;
1424
1425     NewState.PrivilegeCount = 1;
1426     NewState.Privileges[0].Luid.LowPart = Privilege;
1427     NewState.Privileges[0].Luid.HighPart = 0;
1428     NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1429
1430     Status = NtAdjustPrivilegesToken(TokenHandle,
1431                                      FALSE,
1432                                      &NewState,
1433                                      sizeof(TOKEN_PRIVILEGES),
1434                                      &OldState,
1435                                      &ReturnLength);
1436     NtClose (TokenHandle);
1437     if (Status == STATUS_NOT_ALL_ASSIGNED)
1438     {
1439         TRACE("Failed to assign all privileges\n");
1440         return STATUS_PRIVILEGE_NOT_HELD;
1441     }
1442     if (!NT_SUCCESS(Status))
1443     {
1444         WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1445         return Status;
1446     }
1447
1448     if (OldState.PrivilegeCount == 0)
1449         *Enabled = Enable;
1450     else
1451         *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1452
1453     return STATUS_SUCCESS;
1454 }
1455
1456 /******************************************************************************
1457  *  RtlImpersonateSelf          [NTDLL.@]
1458  *
1459  * Makes an impersonation token that represents the process user and assigns
1460  * to the current thread.
1461  *
1462  * PARAMS
1463  *  ImpersonationLevel [I] Level at which to impersonate.
1464  *
1465  * RETURNS
1466  *  Success: STATUS_SUCCESS.
1467  *  Failure: NTSTATUS code.
1468  */
1469 NTSTATUS WINAPI
1470 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1471 {
1472     NTSTATUS Status;
1473     OBJECT_ATTRIBUTES ObjectAttributes;
1474     HANDLE ProcessToken;
1475     HANDLE ImpersonationToken;
1476
1477     TRACE("(%08x)\n", ImpersonationLevel);
1478
1479     Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1480                                  &ProcessToken);
1481     if (Status != STATUS_SUCCESS)
1482         return Status;
1483
1484     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1485
1486     Status = NtDuplicateToken( ProcessToken,
1487                                TOKEN_IMPERSONATE,
1488                                &ObjectAttributes,
1489                                ImpersonationLevel,
1490                                TokenImpersonation,
1491                                &ImpersonationToken );
1492     if (Status != STATUS_SUCCESS)
1493     {
1494         NtClose( ProcessToken );
1495         return Status;
1496     }
1497
1498     Status = NtSetInformationThread( GetCurrentThread(),
1499                                      ThreadImpersonationToken,
1500                                      &ImpersonationToken,
1501                                      sizeof(ImpersonationToken) );
1502
1503     NtClose( ImpersonationToken );
1504     NtClose( ProcessToken );
1505
1506     return Status;
1507 }
1508
1509 /******************************************************************************
1510  *  NtAccessCheck               [NTDLL.@]
1511  *  ZwAccessCheck               [NTDLL.@]
1512  *
1513  * Checks that a user represented by a token is allowed to access an object
1514  * represented by a security descriptor.
1515  *
1516  * PARAMS
1517  *  SecurityDescriptor [I] The security descriptor of the object to check.
1518  *  ClientToken        [I] Token of the user accessing the object.
1519  *  DesiredAccess      [I] The desired access to the object.
1520  *  GenericMapping     [I] Mapping used to transform access rights in the SD to their specific forms.
1521  *  PrivilegeSet       [I/O] Privileges used during the access check.
1522  *  ReturnLength       [O] Number of bytes stored into PrivilegeSet.
1523  *  GrantedAccess      [O] The actual access rights granted.
1524  *  AccessStatus       [O] The status of the access check.
1525  *
1526  * RETURNS
1527  *  NTSTATUS code.
1528  *
1529  * NOTES
1530  *  DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1531  *  the maximum access rights allowed by the SD and returns them in
1532  *  GrantedAccess.
1533  *  The SecurityDescriptor must have a valid owner and groups present,
1534  *  otherwise the function will fail.
1535  */
1536 NTSTATUS WINAPI
1537 NtAccessCheck(
1538     PSECURITY_DESCRIPTOR SecurityDescriptor,
1539     HANDLE ClientToken,
1540     ACCESS_MASK DesiredAccess,
1541     PGENERIC_MAPPING GenericMapping,
1542     PPRIVILEGE_SET PrivilegeSet,
1543     PULONG ReturnLength,
1544     PULONG GrantedAccess,
1545     NTSTATUS *AccessStatus)
1546 {
1547     NTSTATUS status;
1548
1549     TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1550         SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1551         PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1552
1553     if (!PrivilegeSet || !ReturnLength)
1554         return STATUS_ACCESS_VIOLATION;
1555
1556     SERVER_START_REQ( access_check )
1557     {
1558         struct security_descriptor sd;
1559         PSID owner;
1560         PSID group;
1561         PACL sacl;
1562         PACL dacl;
1563         BOOLEAN defaulted, present;
1564         DWORD revision;
1565         SECURITY_DESCRIPTOR_CONTROL control;
1566
1567         req->handle = wine_server_obj_handle( ClientToken );
1568         req->desired_access = DesiredAccess;
1569         req->mapping_read = GenericMapping->GenericRead;
1570         req->mapping_write = GenericMapping->GenericWrite;
1571         req->mapping_execute = GenericMapping->GenericExecute;
1572         req->mapping_all = GenericMapping->GenericAll;
1573
1574         /* marshal security descriptor */
1575         RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1576         sd.control = control & ~SE_SELF_RELATIVE;
1577         RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1578         sd.owner_len = RtlLengthSid( owner );
1579         RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1580         sd.group_len = RtlLengthSid( group );
1581         RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1582         sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1583         RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1584         sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1585
1586         wine_server_add_data( req, &sd, sizeof(sd) );
1587         wine_server_add_data( req, owner, sd.owner_len );
1588         wine_server_add_data( req, group, sd.group_len );
1589         wine_server_add_data( req, sacl, sd.sacl_len );
1590         wine_server_add_data( req, dacl, sd.dacl_len );
1591
1592         wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1593
1594         status = wine_server_call( req );
1595
1596         *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1597         PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1598
1599         if (status == STATUS_SUCCESS)
1600         {
1601             *AccessStatus = reply->access_status;
1602             *GrantedAccess = reply->access_granted;
1603         }
1604     }
1605     SERVER_END_REQ;
1606
1607     return status;
1608 }
1609
1610 /******************************************************************************
1611  *  NtSetSecurityObject         [NTDLL.@]
1612  *  ZwSetSecurityObject         [NTDLL.@]
1613  *
1614  * Sets specified parts of the object's security descriptor.
1615  *
1616  * PARAMS
1617  *  Handle              [I] Handle to the object to change security descriptor of.
1618  *  SecurityInformation [I] Specifies which parts of the security descriptor to set.
1619  *  SecurityDescriptor  [I] New parts of a security descriptor for the object.
1620  *
1621  * RETURNS
1622  *  NTSTATUS code.
1623  *
1624  */
1625 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1626         SECURITY_INFORMATION SecurityInformation,
1627         PSECURITY_DESCRIPTOR SecurityDescriptor)
1628 {
1629     NTSTATUS status;
1630     struct security_descriptor sd;
1631     PACL dacl = NULL, sacl = NULL;
1632     PSID owner = NULL, group = NULL;
1633     BOOLEAN defaulted, present;
1634     DWORD revision;
1635     SECURITY_DESCRIPTOR_CONTROL control;
1636
1637     TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1638
1639     if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1640
1641     memset( &sd, 0, sizeof(sd) );
1642     status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1643     if (status != STATUS_SUCCESS) return status;
1644     sd.control = control & ~SE_SELF_RELATIVE;
1645
1646     if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1647     {
1648         status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1649         if (status != STATUS_SUCCESS) return status;
1650         if (!(sd.owner_len = RtlLengthSid( owner )))
1651             return STATUS_INVALID_SECURITY_DESCR;
1652     }
1653
1654     if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1655     {
1656         status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1657         if (status != STATUS_SUCCESS) return status;
1658         if (!(sd.group_len = RtlLengthSid( group )))
1659             return STATUS_INVALID_SECURITY_DESCR;
1660     }
1661
1662     if (SecurityInformation & SACL_SECURITY_INFORMATION)
1663     {
1664         status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1665         if (status != STATUS_SUCCESS) return status;
1666         sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1667         sd.control |= SE_SACL_PRESENT;
1668     }
1669
1670     if (SecurityInformation & DACL_SECURITY_INFORMATION)
1671     {
1672         status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1673         if (status != STATUS_SUCCESS) return status;
1674         sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1675         sd.control |= SE_DACL_PRESENT;
1676     }
1677
1678     SERVER_START_REQ( set_security_object )
1679     {
1680         req->handle = wine_server_obj_handle( Handle );
1681         req->security_info = SecurityInformation;
1682
1683         wine_server_add_data( req, &sd, sizeof(sd) );
1684         wine_server_add_data( req, owner, sd.owner_len );
1685         wine_server_add_data( req, group, sd.group_len );
1686         wine_server_add_data( req, sacl, sd.sacl_len );
1687         wine_server_add_data( req, dacl, sd.dacl_len );
1688         status = wine_server_call( req );
1689     }
1690     SERVER_END_REQ;
1691
1692     return status;
1693 }
1694
1695 /******************************************************************************
1696  * RtlConvertSidToUnicodeString (NTDLL.@)
1697  *
1698  * The returned SID is used to access the USER registry hive usually
1699  *
1700  * the native function returns something like
1701  * "S-1-5-21-0000000000-000000000-0000000000-500";
1702  */
1703 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1704        PUNICODE_STRING String,
1705        PSID pSid,
1706        BOOLEAN AllocateString)
1707 {
1708     static const WCHAR formatW[] = {'-','%','u',0};
1709     WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1710     WCHAR *p = buffer;
1711     const SID *sid = pSid;
1712     DWORD i, len;
1713
1714     *p++ = 'S';
1715     p += sprintfW( p, formatW, sid->Revision );
1716     p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1717                                                    sid->IdentifierAuthority.Value[4] ),
1718                                          MAKEWORD( sid->IdentifierAuthority.Value[3],
1719                                                    sid->IdentifierAuthority.Value[2] )));
1720     for (i = 0; i < sid->SubAuthorityCount; i++)
1721         p += sprintfW( p, formatW, sid->SubAuthority[i] );
1722
1723     len = (p + 1 - buffer) * sizeof(WCHAR);
1724
1725     String->Length = len - sizeof(WCHAR);
1726     if (AllocateString)
1727     {
1728         String->MaximumLength = len;
1729         if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1730             return STATUS_NO_MEMORY;
1731     }
1732     else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1733
1734     memcpy( String->Buffer, buffer, len );
1735     return STATUS_SUCCESS;
1736 }
1737
1738 /******************************************************************************
1739  * RtlQueryInformationAcl (NTDLL.@)
1740  */
1741 NTSTATUS WINAPI RtlQueryInformationAcl(
1742     PACL pAcl,
1743     LPVOID pAclInformation,
1744     DWORD nAclInformationLength,
1745     ACL_INFORMATION_CLASS dwAclInformationClass)
1746 {
1747     NTSTATUS status = STATUS_SUCCESS;
1748
1749     TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n", 
1750         pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1751
1752     switch (dwAclInformationClass)
1753     {
1754         case AclRevisionInformation:
1755         {
1756             PACL_REVISION_INFORMATION paclrev = pAclInformation;
1757
1758             if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1759                 status = STATUS_INVALID_PARAMETER;
1760             else
1761                 paclrev->AclRevision = pAcl->AclRevision;
1762
1763             break;
1764         }
1765
1766         case AclSizeInformation:
1767         {
1768             PACL_SIZE_INFORMATION paclsize = pAclInformation;
1769
1770             if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1771                 status = STATUS_INVALID_PARAMETER;
1772             else
1773             {
1774                 paclsize->AceCount = pAcl->AceCount;
1775                 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1776                 if (pAcl->AclSize < paclsize->AclBytesInUse)
1777                 {
1778                     WARN("Acl uses %d bytes, but only has %d allocated!  Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1779                     paclsize->AclBytesFree = 0;
1780                     paclsize->AclBytesInUse = pAcl->AclSize;
1781                 }
1782                 else
1783                     paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1784             }
1785
1786             break;
1787         }
1788
1789         default:
1790             WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1791             status = STATUS_INVALID_PARAMETER;
1792     }
1793
1794     return status;
1795 }