includes: Fix alignment for 64-bits
[wine/wine64.git] / dlls / ntdll / sec.c
bloba3a7148db7f1dd08fb0b0a4a17edd6c006e00965
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
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
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"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 /* helper function to retrieve active length of an ACL */
49 static size_t acl_bytesInUse(PACL pAcl)
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++)
56 bytesInUse += ace->AceSize;
57 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
59 return bytesInUse;
62 /* helper function to copy an ACL */
63 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
65 DWORD size;
67 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
68 return FALSE;
70 size = pSourceAcl->AclSize;
71 if (nDestinationAclLength < size)
72 return FALSE;
74 memmove(pDestinationAcl, pSourceAcl, size);
75 return TRUE;
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)
82 ACE_HEADER *pAceHeader;
83 DWORD dwLengthSid;
84 DWORD dwAceSize;
85 DWORD *pAccessMask;
86 DWORD *pSidStart;
88 if (!RtlValidSid(pSid))
89 return STATUS_INVALID_SID;
91 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
92 return STATUS_REVISION_MISMATCH;
94 if (!RtlValidAcl(pAcl))
95 return STATUS_INVALID_ACL;
97 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
98 return STATUS_INVALID_ACL;
100 if (!pAceHeader)
101 return STATUS_ALLOTTED_SPACE_EXCEEDED;
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;
109 /* fill the new ACE */
110 pAceHeader->AceType = dwAceType;
111 pAceHeader->AceFlags = dwAceFlags;
112 pAceHeader->AceSize = dwAceSize;
114 /* skip past the ACE_HEADER of the ACE */
115 pAccessMask = (DWORD *)(pAceHeader + 1);
116 *pAccessMask = dwAccessMask;
118 /* skip past ACE->Mask */
119 pSidStart = pAccessMask + 1;
120 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
122 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
123 pAcl->AceCount++;
125 return STATUS_SUCCESS;
129 * SID FUNCTIONS
132 /******************************************************************************
133 * RtlAllocateAndInitializeSid [NTDLL.@]
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 )
145 SID *tmp_sid;
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);
152 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
154 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
155 RtlLengthRequiredSid(nSubAuthorityCount))))
156 return STATUS_NO_MEMORY;
158 tmp_sid->Revision = SID_REVISION;
160 if (pIdentifierAuthority)
161 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
162 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
164 switch( nSubAuthorityCount )
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;
176 *pSid = tmp_sid;
177 return STATUS_SUCCESS;
180 /******************************************************************************
181 * RtlEqualSid [NTDLL.@]
183 * Determine if two SIDs are equal.
185 * PARAMS
186 * pSid1 [I] Source SID
187 * pSid2 [I] SID to compare with
189 * RETURNS
190 * TRUE, if pSid1 is equal to pSid2,
191 * FALSE otherwise.
193 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
195 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
196 return FALSE;
198 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
199 return FALSE;
201 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
202 return FALSE;
204 return TRUE;
207 /******************************************************************************
208 * RtlEqualPrefixSid [NTDLL.@]
210 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
212 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
213 return FALSE;
215 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
216 return FALSE;
218 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
219 return FALSE;
221 return TRUE;
225 /******************************************************************************
226 * RtlFreeSid [NTDLL.@]
228 * Free the resources used by a SID.
230 * PARAMS
231 * pSid [I] SID to Free.
233 * RETURNS
234 * STATUS_SUCCESS.
236 DWORD WINAPI RtlFreeSid(PSID pSid)
238 TRACE("(%p)\n", pSid);
239 RtlFreeHeap( GetProcessHeap(), 0, pSid );
240 return STATUS_SUCCESS;
243 /**************************************************************************
244 * RtlLengthRequiredSid [NTDLL.@]
246 * Determine the amount of memory a SID will use
248 * PARAMS
249 * nrofsubauths [I] Number of Sub Authorities in the SID.
251 * RETURNS
252 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
254 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
256 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
259 /**************************************************************************
260 * RtlLengthSid [NTDLL.@]
262 * Determine the amount of memory a SID is using
264 * PARAMS
265 * pSid [I] SID to get the size of.
267 * RETURNS
268 * The size, in bytes, of pSid.
270 DWORD WINAPI RtlLengthSid(PSID pSid)
272 TRACE("sid=%p\n",pSid);
273 if (!pSid) return 0;
274 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
277 /**************************************************************************
278 * RtlInitializeSid [NTDLL.@]
280 * Initialise a SID.
282 * PARAMS
283 * pSid [I] SID to initialise
284 * pIdentifierAuthority [I] Identifier Authority
285 * nSubAuthorityCount [I] Number of Sub Authorities
287 * RETURNS
288 * Success: TRUE. pSid is initialised with the details given.
289 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
291 BOOL WINAPI RtlInitializeSid(
292 PSID pSid,
293 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
294 BYTE nSubAuthorityCount)
296 int i;
297 SID* pisid=pSid;
299 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
300 return FALSE;
302 pisid->Revision = SID_REVISION;
303 pisid->SubAuthorityCount = nSubAuthorityCount;
304 if (pIdentifierAuthority)
305 pisid->IdentifierAuthority = *pIdentifierAuthority;
307 for (i = 0; i < nSubAuthorityCount; i++)
308 *RtlSubAuthoritySid(pSid, i) = 0;
310 return TRUE;
313 /**************************************************************************
314 * RtlSubAuthoritySid [NTDLL.@]
316 * Return the Sub Authority of a SID
318 * PARAMS
319 * pSid [I] SID to get the Sub Authority from.
320 * nSubAuthority [I] Sub Authority number.
322 * RETURNS
323 * A pointer to The Sub Authority value of pSid.
325 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
327 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
330 /**************************************************************************
331 * RtlIdentifierAuthoritySid [NTDLL.@]
333 * Return the Identifier Authority of a SID.
335 * PARAMS
336 * pSid [I] SID to get the Identifier Authority from.
338 * RETURNS
339 * A pointer to the Identifier Authority value of pSid.
341 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
343 return &(((SID*)pSid)->IdentifierAuthority);
346 /**************************************************************************
347 * RtlSubAuthorityCountSid [NTDLL.@]
349 * Get the number of Sub Authorities in a SID.
351 * PARAMS
352 * pSid [I] SID to get the count from.
354 * RETURNS
355 * A pointer to the Sub Authority count of pSid.
357 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
359 return &(((SID*)pSid)->SubAuthorityCount);
362 /**************************************************************************
363 * RtlCopySid [NTDLL.@]
365 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
367 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
368 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
369 return FALSE;
371 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
372 return FALSE;
374 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
375 return TRUE;
377 /******************************************************************************
378 * RtlValidSid [NTDLL.@]
380 * Determine if a SID is valid.
382 * PARAMS
383 * pSid [I] SID to check
385 * RETURNS
386 * TRUE if pSid is valid,
387 * FALSE otherwise.
389 BOOLEAN WINAPI RtlValidSid( PSID pSid )
391 BOOL ret;
392 __TRY
394 ret = TRUE;
395 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
396 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
398 ret = FALSE;
401 __EXCEPT_PAGE_FAULT
403 WARN("(%p): invalid pointer!\n", pSid);
404 return FALSE;
406 __ENDTRY
407 return ret;
412 * security descriptor functions
415 /**************************************************************************
416 * RtlCreateSecurityDescriptor [NTDLL.@]
418 * Initialise a SECURITY_DESCRIPTOR.
420 * PARAMS
421 * lpsd [O] Descriptor to initialise.
422 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
424 * RETURNS
425 * Success: STATUS_SUCCESS.
426 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
428 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
429 PSECURITY_DESCRIPTOR lpsd,
430 DWORD rev)
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;
439 /**************************************************************************
440 * RtlCopySecurityDescriptor [NTDLL.@]
442 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
444 * PARAMS
445 * pSourceSD [O] SD to copy from.
446 * pDestinationSD [I] Destination SD.
448 * RETURNS
449 * Success: STATUS_SUCCESS.
450 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
452 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
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;
462 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
465 /* copy initial data */
466 destSD->Revision = srcSD->Revision;
467 destSD->Sbz1 = srcSD->Sbz1;
468 destSD->Control = srcSD->Control;
470 /* copy Owner */
471 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
472 length = RtlLengthSid(Owner);
474 if (isSelfRelative)
476 destSD->Owner = srcSD->Owner;
477 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
479 else
481 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
482 RtlCopySid(length, destSD->Owner, Owner);
485 /* copy Group */
486 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
487 length = RtlLengthSid(Group);
489 if (isSelfRelative)
491 destSD->Group = srcSD->Group;
492 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
494 else
496 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
497 RtlCopySid(length, destSD->Group, Group);
500 /* copy Dacl */
501 if (srcSD->Control & SE_DACL_PRESENT)
503 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
504 length = Dacl->AclSize;
506 if (isSelfRelative)
508 destSD->Dacl = srcSD->Dacl;
509 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
511 else
513 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, destSD->Dacl, Dacl);
518 /* copy Sacl */
519 if (srcSD->Control & SE_SACL_PRESENT)
521 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
522 length = Sacl->AclSize;
524 if (isSelfRelative)
526 destSD->Sacl = srcSD->Sacl;
527 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
529 else
531 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
532 copy_acl(length, destSD->Sacl, Sacl);
536 return STATUS_SUCCESS;
539 /**************************************************************************
540 * RtlValidSecurityDescriptor [NTDLL.@]
542 * Determine if a SECURITY_DESCRIPTOR is valid.
544 * PARAMS
545 * SecurityDescriptor [I] Descriptor to check.
547 * RETURNS
548 * Success: STATUS_SUCCESS.
549 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
551 NTSTATUS WINAPI RtlValidSecurityDescriptor(
552 PSECURITY_DESCRIPTOR SecurityDescriptor)
554 if ( ! SecurityDescriptor )
555 return STATUS_INVALID_SECURITY_DESCR;
556 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
557 return STATUS_UNKNOWN_REVISION;
559 return STATUS_SUCCESS;
562 /**************************************************************************
563 * RtlLengthSecurityDescriptor [NTDLL.@]
565 ULONG WINAPI RtlLengthSecurityDescriptor(
566 PSECURITY_DESCRIPTOR pSecurityDescriptor)
568 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
569 ULONG_PTR offset = 0;
570 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
572 if ( lpsd == NULL )
573 return 0;
575 if ( lpsd->Control & SE_SELF_RELATIVE)
576 offset = (ULONG_PTR) lpsd;
578 if ( lpsd->Owner != NULL )
579 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
581 if ( lpsd->Group != NULL )
582 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
584 if ( (lpsd->Control & SE_SACL_PRESENT) &&
585 lpsd->Sacl != NULL )
586 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
588 if ( (lpsd->Control & SE_DACL_PRESENT) &&
589 lpsd->Dacl != NULL )
590 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
592 return Size;
595 /******************************************************************************
596 * RtlGetDaclSecurityDescriptor [NTDLL.@]
599 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
600 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
601 OUT PBOOLEAN lpbDaclPresent,
602 OUT PACL *pDacl,
603 OUT PBOOLEAN lpbDaclDefaulted)
605 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
607 TRACE("(%p,%p,%p,%p)\n",
608 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
610 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
611 return STATUS_UNKNOWN_REVISION ;
613 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
615 if ( SE_SELF_RELATIVE & lpsd->Control)
616 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
617 else
618 *pDacl = lpsd->Dacl;
620 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
623 return STATUS_SUCCESS;
626 /**************************************************************************
627 * RtlSetDaclSecurityDescriptor [NTDLL.@]
629 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
630 PSECURITY_DESCRIPTOR pSecurityDescriptor,
631 BOOLEAN daclpresent,
632 PACL dacl,
633 BOOLEAN dacldefaulted )
635 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
637 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
638 return STATUS_UNKNOWN_REVISION;
639 if (lpsd->Control & SE_SELF_RELATIVE)
640 return STATUS_INVALID_SECURITY_DESCR;
642 if (!daclpresent)
644 lpsd->Control &= ~SE_DACL_PRESENT;
645 return STATUS_SUCCESS;
648 lpsd->Control |= SE_DACL_PRESENT;
649 lpsd->Dacl = dacl;
651 if (dacldefaulted)
652 lpsd->Control |= SE_DACL_DEFAULTED;
653 else
654 lpsd->Control &= ~SE_DACL_DEFAULTED;
656 return STATUS_SUCCESS;
659 /******************************************************************************
660 * RtlGetSaclSecurityDescriptor [NTDLL.@]
663 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
664 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
665 OUT PBOOLEAN lpbSaclPresent,
666 OUT PACL *pSacl,
667 OUT PBOOLEAN lpbSaclDefaulted)
669 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
671 TRACE("(%p,%p,%p,%p)\n",
672 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
674 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
675 return STATUS_UNKNOWN_REVISION;
677 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
679 if (SE_SELF_RELATIVE & lpsd->Control)
680 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
681 else
682 *pSacl = lpsd->Sacl;
684 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
687 return STATUS_SUCCESS;
690 /**************************************************************************
691 * RtlSetSaclSecurityDescriptor [NTDLL.@]
693 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
694 PSECURITY_DESCRIPTOR pSecurityDescriptor,
695 BOOLEAN saclpresent,
696 PACL sacl,
697 BOOLEAN sacldefaulted)
699 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
701 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
702 return STATUS_UNKNOWN_REVISION;
703 if (lpsd->Control & SE_SELF_RELATIVE)
704 return STATUS_INVALID_SECURITY_DESCR;
705 if (!saclpresent) {
706 lpsd->Control &= ~SE_SACL_PRESENT;
707 return 0;
709 lpsd->Control |= SE_SACL_PRESENT;
710 lpsd->Sacl = sacl;
711 if (sacldefaulted)
712 lpsd->Control |= SE_SACL_DEFAULTED;
713 else
714 lpsd->Control &= ~SE_SACL_DEFAULTED;
715 return STATUS_SUCCESS;
718 /**************************************************************************
719 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
721 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
722 PSECURITY_DESCRIPTOR pSecurityDescriptor,
723 PSID *Owner,
724 PBOOLEAN OwnerDefaulted)
726 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
728 if ( !lpsd || !Owner || !OwnerDefaulted )
729 return STATUS_INVALID_PARAMETER;
731 if ( lpsd->Control & SE_OWNER_DEFAULTED )
732 *OwnerDefaulted = TRUE;
733 else
734 *OwnerDefaulted = FALSE;
736 if (lpsd->Owner != NULL)
738 if (lpsd->Control & SE_SELF_RELATIVE)
739 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
740 else
741 *Owner = lpsd->Owner;
744 else
745 *Owner = NULL;
747 return STATUS_SUCCESS;
750 /**************************************************************************
751 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
753 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
754 PSECURITY_DESCRIPTOR pSecurityDescriptor,
755 PSID owner,
756 BOOLEAN ownerdefaulted)
758 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
760 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
761 return STATUS_UNKNOWN_REVISION;
762 if (lpsd->Control & SE_SELF_RELATIVE)
763 return STATUS_INVALID_SECURITY_DESCR;
765 lpsd->Owner = owner;
766 if (ownerdefaulted)
767 lpsd->Control |= SE_OWNER_DEFAULTED;
768 else
769 lpsd->Control &= ~SE_OWNER_DEFAULTED;
770 return STATUS_SUCCESS;
773 /**************************************************************************
774 * RtlSetGroupSecurityDescriptor [NTDLL.@]
776 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
777 PSECURITY_DESCRIPTOR pSecurityDescriptor,
778 PSID group,
779 BOOLEAN groupdefaulted)
781 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
783 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
784 return STATUS_UNKNOWN_REVISION;
785 if (lpsd->Control & SE_SELF_RELATIVE)
786 return STATUS_INVALID_SECURITY_DESCR;
788 lpsd->Group = group;
789 if (groupdefaulted)
790 lpsd->Control |= SE_GROUP_DEFAULTED;
791 else
792 lpsd->Control &= ~SE_GROUP_DEFAULTED;
793 return STATUS_SUCCESS;
796 /**************************************************************************
797 * RtlGetGroupSecurityDescriptor [NTDLL.@]
799 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
800 PSECURITY_DESCRIPTOR pSecurityDescriptor,
801 PSID *Group,
802 PBOOLEAN GroupDefaulted)
804 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
806 if ( !lpsd || !Group || !GroupDefaulted )
807 return STATUS_INVALID_PARAMETER;
809 if ( lpsd->Control & SE_GROUP_DEFAULTED )
810 *GroupDefaulted = TRUE;
811 else
812 *GroupDefaulted = FALSE;
814 if (lpsd->Group != NULL)
816 if (lpsd->Control & SE_SELF_RELATIVE)
817 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
818 else
819 *Group = lpsd->Group;
821 else
822 *Group = NULL;
824 return STATUS_SUCCESS;
827 /**************************************************************************
828 * RtlMakeSelfRelativeSD [NTDLL.@]
830 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
831 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
832 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
833 IN OUT LPDWORD lpdwBufferLength)
835 ULONG_PTR offsetRel;
836 ULONG length;
837 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
838 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
840 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
841 lpdwBufferLength ? *lpdwBufferLength: -1);
843 if (!lpdwBufferLength || !pAbs)
844 return STATUS_INVALID_PARAMETER;
846 length = RtlLengthSecurityDescriptor(pAbs);
847 if (*lpdwBufferLength < length)
849 *lpdwBufferLength = length;
850 return STATUS_BUFFER_TOO_SMALL;
853 if (!pRel)
854 return STATUS_INVALID_PARAMETER;
856 if (pAbs->Control & SE_SELF_RELATIVE)
858 memcpy(pRel, pAbs, length);
859 return STATUS_SUCCESS;
862 pRel->Revision = pAbs->Revision;
863 pRel->Sbz1 = pAbs->Sbz1;
864 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
866 offsetRel = sizeof(SECURITY_DESCRIPTOR);
867 if (pAbs->Owner)
869 pRel->Owner = (PSID) offsetRel;
870 length = RtlLengthSid(pAbs->Owner);
871 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
872 offsetRel += length;
874 else
876 pRel->Owner = NULL;
879 if (pAbs->Group)
881 pRel->Group = (PSID) offsetRel;
882 length = RtlLengthSid(pAbs->Group);
883 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
884 offsetRel += length;
886 else
888 pRel->Group = NULL;
891 if (pAbs->Sacl)
893 pRel->Sacl = (PACL) offsetRel;
894 length = pAbs->Sacl->AclSize;
895 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
896 offsetRel += length;
898 else
900 pRel->Sacl = NULL;
903 if (pAbs->Dacl)
905 pRel->Dacl = (PACL) offsetRel;
906 length = pAbs->Dacl->AclSize;
907 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
909 else
911 pRel->Dacl = NULL;
914 return STATUS_SUCCESS;
918 /**************************************************************************
919 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
921 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
922 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
923 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
924 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
925 OUT PACL pDacl,
926 OUT LPDWORD lpdwDaclSize,
927 OUT PACL pSacl,
928 OUT LPDWORD lpdwSaclSize,
929 OUT PSID pOwner,
930 OUT LPDWORD lpdwOwnerSize,
931 OUT PSID pPrimaryGroup,
932 OUT LPDWORD lpdwPrimaryGroupSize)
934 NTSTATUS status = STATUS_SUCCESS;
935 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
936 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
938 if (!pRel ||
939 !lpdwAbsoluteSecurityDescriptorSize ||
940 !lpdwDaclSize ||
941 !lpdwSaclSize ||
942 !lpdwOwnerSize ||
943 !lpdwPrimaryGroupSize ||
944 ~pRel->Control & SE_SELF_RELATIVE)
945 return STATUS_INVALID_PARAMETER;
947 /* Confirm buffers are sufficiently large */
948 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
950 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
951 status = STATUS_BUFFER_TOO_SMALL;
954 if (pRel->Control & SE_DACL_PRESENT &&
955 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
957 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (pRel->Control & SE_SACL_PRESENT &&
962 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
964 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
965 status = STATUS_BUFFER_TOO_SMALL;
968 if (pRel->Owner &&
969 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
971 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (pRel->Group &&
976 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
978 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
979 status = STATUS_BUFFER_TOO_SMALL;
982 if (status != STATUS_SUCCESS)
983 return status;
985 /* Copy structures, and clear the ones we don't set */
986 pAbs->Revision = pRel->Revision;
987 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
988 pAbs->Sacl = NULL;
989 pAbs->Dacl = NULL;
990 pAbs->Owner = NULL;
991 pAbs->Group = NULL;
993 if (pRel->Control & SE_SACL_PRESENT)
995 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
997 memcpy(pSacl, pAcl, pAcl->AclSize);
998 pAbs->Sacl = pSacl;
1001 if (pRel->Control & SE_DACL_PRESENT)
1003 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1004 memcpy(pDacl, pAcl, pAcl->AclSize);
1005 pAbs->Dacl = pDacl;
1008 if (pRel->Owner)
1010 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1011 memcpy(pOwner, psid, RtlLengthSid(psid));
1012 pAbs->Owner = pOwner;
1015 if (pRel->Group)
1017 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1018 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1019 pAbs->Group = pPrimaryGroup;
1022 return status;
1025 /******************************************************************************
1026 * RtlGetControlSecurityDescriptor (NTDLL.@)
1028 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1029 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1030 PSECURITY_DESCRIPTOR_CONTROL pControl,
1031 LPDWORD lpdwRevision)
1033 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1035 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1037 *lpdwRevision = lpsd->Revision;
1039 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1040 return STATUS_UNKNOWN_REVISION;
1042 *pControl = lpsd->Control;
1044 return STATUS_SUCCESS;
1047 /******************************************************************************
1048 * RtlSetControlSecurityDescriptor (NTDLL.@)
1050 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1051 PSECURITY_DESCRIPTOR SecurityDescriptor,
1052 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1053 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1055 SECURITY_DESCRIPTOR_CONTROL const immutable
1056 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1057 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1058 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1059 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1062 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1064 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1065 ControlBitsOfInterest, ControlBitsToSet);
1067 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1068 return STATUS_INVALID_PARAMETER;
1070 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1071 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1073 return STATUS_SUCCESS;
1077 /**************************************************************************
1078 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1080 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1081 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1082 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1083 PULONG BufferLength)
1085 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1087 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1088 SelfRelativeSecurityDescriptor, BufferLength);
1090 if (abs->Control & SE_SELF_RELATIVE)
1091 return STATUS_BAD_DESCRIPTOR_FORMAT;
1093 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1094 SelfRelativeSecurityDescriptor, BufferLength);
1099 * access control list's
1102 /**************************************************************************
1103 * RtlCreateAcl [NTDLL.@]
1105 * NOTES
1106 * This should return NTSTATUS
1108 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1110 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1112 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1113 return STATUS_INVALID_PARAMETER;
1114 if (size<sizeof(ACL))
1115 return STATUS_BUFFER_TOO_SMALL;
1116 if (size>0xFFFF)
1117 return STATUS_INVALID_PARAMETER;
1119 memset(acl,'\0',sizeof(ACL));
1120 acl->AclRevision = rev;
1121 acl->AclSize = size;
1122 acl->AceCount = 0;
1123 return STATUS_SUCCESS;
1126 /**************************************************************************
1127 * RtlFirstFreeAce [NTDLL.@]
1128 * looks for the AceCount+1 ACE, and if it is still within the alloced
1129 * ACL, return a pointer to it
1131 BOOLEAN WINAPI RtlFirstFreeAce(
1132 PACL acl,
1133 PACE_HEADER *x)
1135 PACE_HEADER ace;
1136 int i;
1138 *x = 0;
1139 ace = (PACE_HEADER)(acl+1);
1140 for (i=0;i<acl->AceCount;i++) {
1141 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1142 return 0;
1143 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1145 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1146 return 0;
1147 *x = ace;
1148 return 1;
1151 /**************************************************************************
1152 * RtlAddAce [NTDLL.@]
1154 NTSTATUS WINAPI RtlAddAce(
1155 PACL acl,
1156 DWORD rev,
1157 DWORD xnrofaces,
1158 PACE_HEADER acestart,
1159 DWORD acelen)
1161 PACE_HEADER ace,targetace;
1162 int nrofaces;
1164 if (acl->AclRevision != ACL_REVISION)
1165 return STATUS_INVALID_PARAMETER;
1166 if (!RtlFirstFreeAce(acl,&targetace))
1167 return STATUS_INVALID_PARAMETER;
1168 nrofaces=0;ace=acestart;
1169 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1170 nrofaces++;
1171 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1173 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1174 return STATUS_INVALID_PARAMETER;
1175 memcpy((LPBYTE)targetace,acestart,acelen);
1176 acl->AceCount+=nrofaces;
1177 return STATUS_SUCCESS;
1180 /**************************************************************************
1181 * RtlDeleteAce [NTDLL.@]
1183 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1185 NTSTATUS status;
1186 PACE_HEADER pAce;
1188 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1190 if (STATUS_SUCCESS == status)
1192 PACE_HEADER pcAce;
1193 DWORD len = 0;
1195 /* skip over the ACE we are deleting */
1196 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1197 dwAceIndex++;
1199 /* calculate the length of the rest */
1200 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1202 len += pcAce->AceSize;
1203 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1206 /* slide them all backwards */
1207 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1208 pAcl->AceCount--;
1211 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1213 return status;
1216 /******************************************************************************
1217 * RtlAddAccessAllowedAce [NTDLL.@]
1219 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1220 IN OUT PACL pAcl,
1221 IN DWORD dwAceRevision,
1222 IN DWORD AccessMask,
1223 IN PSID pSid)
1225 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1228 /******************************************************************************
1229 * RtlAddAccessAllowedAceEx [NTDLL.@]
1231 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1232 IN OUT PACL pAcl,
1233 IN DWORD dwAceRevision,
1234 IN DWORD AceFlags,
1235 IN DWORD AccessMask,
1236 IN PSID pSid)
1238 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1240 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1241 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1244 /******************************************************************************
1245 * RtlAddAccessDeniedAce [NTDLL.@]
1247 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1248 IN OUT PACL pAcl,
1249 IN DWORD dwAceRevision,
1250 IN DWORD AccessMask,
1251 IN PSID pSid)
1253 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1256 /******************************************************************************
1257 * RtlAddAccessDeniedAceEx [NTDLL.@]
1259 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1260 IN OUT PACL pAcl,
1261 IN DWORD dwAceRevision,
1262 IN DWORD AceFlags,
1263 IN DWORD AccessMask,
1264 IN PSID pSid)
1266 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1268 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1269 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1272 /**************************************************************************
1273 * RtlAddAuditAccessAce [NTDLL.@]
1275 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1276 IN OUT PACL pAcl,
1277 IN DWORD dwAceRevision,
1278 IN DWORD dwAceFlags,
1279 IN DWORD dwAccessMask,
1280 IN PSID pSid,
1281 IN BOOL bAuditSuccess,
1282 IN BOOL bAuditFailure)
1284 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1285 pSid,bAuditSuccess,bAuditFailure);
1287 if (bAuditSuccess)
1288 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1290 if (bAuditFailure)
1291 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1293 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1294 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1297 /**************************************************************************
1298 * RtlAddAuditAccessAce [NTDLL.@]
1300 NTSTATUS WINAPI RtlAddAuditAccessAce(
1301 IN OUT PACL pAcl,
1302 IN DWORD dwAceRevision,
1303 IN DWORD dwAccessMask,
1304 IN PSID pSid,
1305 IN BOOL bAuditSuccess,
1306 IN BOOL bAuditFailure)
1308 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1311 /******************************************************************************
1312 * RtlValidAcl [NTDLL.@]
1314 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1316 BOOLEAN ret;
1317 TRACE("(%p)\n", pAcl);
1319 __TRY
1321 PACE_HEADER ace;
1322 int i;
1324 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1325 pAcl->AclRevision > MAX_ACL_REVISION)
1326 ret = FALSE;
1327 else
1329 ace = (PACE_HEADER)(pAcl+1);
1330 ret = TRUE;
1331 for (i=0;i<=pAcl->AceCount;i++)
1333 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1335 ret = FALSE;
1336 break;
1338 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1342 __EXCEPT_PAGE_FAULT
1344 WARN("(%p): invalid pointer!\n", pAcl);
1345 return 0;
1347 __ENDTRY
1348 return ret;
1351 /******************************************************************************
1352 * RtlGetAce [NTDLL.@]
1354 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1356 PACE_HEADER ace;
1358 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1360 if (dwAceIndex >= pAcl->AceCount)
1361 return STATUS_INVALID_PARAMETER;
1363 ace = (PACE_HEADER)(pAcl + 1);
1364 for (;dwAceIndex;dwAceIndex--)
1365 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1367 *pAce = (LPVOID) ace;
1369 return STATUS_SUCCESS;
1373 * misc
1376 /******************************************************************************
1377 * RtlAdjustPrivilege [NTDLL.@]
1379 * Enables or disables a privilege from the calling thread or process.
1381 * PARAMS
1382 * Privilege [I] Privilege index to change.
1383 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1384 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1385 * Enabled [O] Whether privilege was previously enabled or disabled.
1387 * RETURNS
1388 * Success: STATUS_SUCCESS.
1389 * Failure: NTSTATUS code.
1391 * SEE ALSO
1392 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1395 NTSTATUS WINAPI
1396 RtlAdjustPrivilege(ULONG Privilege,
1397 BOOLEAN Enable,
1398 BOOLEAN CurrentThread,
1399 PBOOLEAN Enabled)
1401 TOKEN_PRIVILEGES NewState;
1402 TOKEN_PRIVILEGES OldState;
1403 ULONG ReturnLength;
1404 HANDLE TokenHandle;
1405 NTSTATUS Status;
1407 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1408 CurrentThread ? "TRUE" : "FALSE", Enabled);
1410 if (CurrentThread)
1412 Status = NtOpenThreadToken(GetCurrentThread(),
1413 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1414 FALSE,
1415 &TokenHandle);
1417 else
1419 Status = NtOpenProcessToken(GetCurrentProcess(),
1420 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1421 &TokenHandle);
1424 if (!NT_SUCCESS(Status))
1426 WARN("Retrieving token handle failed (Status %x)\n", Status);
1427 return Status;
1430 OldState.PrivilegeCount = 1;
1432 NewState.PrivilegeCount = 1;
1433 NewState.Privileges[0].Luid.LowPart = Privilege;
1434 NewState.Privileges[0].Luid.HighPart = 0;
1435 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1437 Status = NtAdjustPrivilegesToken(TokenHandle,
1438 FALSE,
1439 &NewState,
1440 sizeof(TOKEN_PRIVILEGES),
1441 &OldState,
1442 &ReturnLength);
1443 NtClose (TokenHandle);
1444 if (Status == STATUS_NOT_ALL_ASSIGNED)
1446 TRACE("Failed to assign all privileges\n");
1447 return STATUS_PRIVILEGE_NOT_HELD;
1449 if (!NT_SUCCESS(Status))
1451 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1452 return Status;
1455 if (OldState.PrivilegeCount == 0)
1456 *Enabled = Enable;
1457 else
1458 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1460 return STATUS_SUCCESS;
1463 /******************************************************************************
1464 * RtlImpersonateSelf [NTDLL.@]
1466 * Makes an impersonation token that represents the process user and assigns
1467 * to the current thread.
1469 * PARAMS
1470 * ImpersonationLevel [I] Level at which to impersonate.
1472 * RETURNS
1473 * Success: STATUS_SUCCESS.
1474 * Failure: NTSTATUS code.
1476 NTSTATUS WINAPI
1477 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1479 NTSTATUS Status;
1480 OBJECT_ATTRIBUTES ObjectAttributes;
1481 HANDLE ProcessToken;
1482 HANDLE ImpersonationToken;
1484 TRACE("(%08x)\n", ImpersonationLevel);
1486 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1487 &ProcessToken);
1488 if (Status != STATUS_SUCCESS)
1489 return Status;
1491 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1493 Status = NtDuplicateToken( ProcessToken,
1494 TOKEN_IMPERSONATE,
1495 &ObjectAttributes,
1496 ImpersonationLevel,
1497 TokenImpersonation,
1498 &ImpersonationToken );
1499 if (Status != STATUS_SUCCESS)
1501 NtClose( ProcessToken );
1502 return Status;
1505 Status = NtSetInformationThread( GetCurrentThread(),
1506 ThreadImpersonationToken,
1507 &ImpersonationToken,
1508 sizeof(ImpersonationToken) );
1510 NtClose( ImpersonationToken );
1511 NtClose( ProcessToken );
1513 return Status;
1516 /******************************************************************************
1517 * NtAccessCheck [NTDLL.@]
1518 * ZwAccessCheck [NTDLL.@]
1520 * Checks that a user represented by a token is allowed to access an object
1521 * represented by a security descriptor.
1523 * PARAMS
1524 * SecurityDescriptor [I] The security descriptor of the object to check.
1525 * ClientToken [I] Token of the user accessing the object.
1526 * DesiredAccess [I] The desired access to the object.
1527 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1528 * PrivilegeSet [I/O] Privileges used during the access check.
1529 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1530 * GrantedAccess [O] The actual access rights granted.
1531 * AccessStatus [O] The status of the access check.
1533 * RETURNS
1534 * NTSTATUS code.
1536 * NOTES
1537 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1538 * the maximum access rights allowed by the SD and returns them in
1539 * GrantedAccess.
1540 * The SecurityDescriptor must have a valid owner and groups present,
1541 * otherwise the function will fail.
1543 NTSTATUS WINAPI
1544 NtAccessCheck(
1545 PSECURITY_DESCRIPTOR SecurityDescriptor,
1546 HANDLE ClientToken,
1547 ACCESS_MASK DesiredAccess,
1548 PGENERIC_MAPPING GenericMapping,
1549 PPRIVILEGE_SET PrivilegeSet,
1550 PULONG ReturnLength,
1551 PULONG GrantedAccess,
1552 NTSTATUS *AccessStatus)
1554 NTSTATUS status;
1556 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1557 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1558 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1560 SERVER_START_REQ( access_check )
1562 struct security_descriptor sd;
1563 PSID owner;
1564 PSID group;
1565 PACL sacl;
1566 PACL dacl;
1567 BOOLEAN defaulted, present;
1568 DWORD revision;
1569 SECURITY_DESCRIPTOR_CONTROL control;
1571 req->handle = wine_server_obj_handle( ClientToken );
1572 req->desired_access = DesiredAccess;
1573 req->mapping_read = GenericMapping->GenericRead;
1574 req->mapping_write = GenericMapping->GenericWrite;
1575 req->mapping_execute = GenericMapping->GenericExecute;
1576 req->mapping_all = GenericMapping->GenericAll;
1578 /* marshal security descriptor */
1579 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1580 sd.control = control & ~SE_SELF_RELATIVE;
1581 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1582 sd.owner_len = RtlLengthSid( owner );
1583 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1584 sd.group_len = RtlLengthSid( group );
1585 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1586 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1587 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1588 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1590 wine_server_add_data( req, &sd, sizeof(sd) );
1591 wine_server_add_data( req, owner, sd.owner_len );
1592 wine_server_add_data( req, group, sd.group_len );
1593 wine_server_add_data( req, sacl, sd.sacl_len );
1594 wine_server_add_data( req, dacl, sd.dacl_len );
1596 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1598 status = wine_server_call( req );
1600 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1601 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1603 if (status == STATUS_SUCCESS)
1605 *AccessStatus = reply->access_status;
1606 *GrantedAccess = reply->access_granted;
1609 SERVER_END_REQ;
1611 return status;
1614 /******************************************************************************
1615 * NtSetSecurityObject [NTDLL.@]
1616 * ZwSetSecurityObject [NTDLL.@]
1618 * Sets specified parts of the object's security descriptor.
1620 * PARAMS
1621 * Handle [I] Handle to the object to change security descriptor of.
1622 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1623 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1625 * RETURNS
1626 * NTSTATUS code.
1629 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1630 SECURITY_INFORMATION SecurityInformation,
1631 PSECURITY_DESCRIPTOR SecurityDescriptor)
1633 NTSTATUS status;
1634 struct security_descriptor sd;
1635 PACL dacl = NULL, sacl = NULL;
1636 PSID owner = NULL, group = NULL;
1637 BOOLEAN defaulted, present;
1638 DWORD revision;
1639 SECURITY_DESCRIPTOR_CONTROL control;
1641 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1643 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1645 memset( &sd, 0, sizeof(sd) );
1646 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1647 if (status != STATUS_SUCCESS) return status;
1648 sd.control = control & ~SE_SELF_RELATIVE;
1650 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1652 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1653 if (status != STATUS_SUCCESS) return status;
1654 if (!(sd.owner_len = RtlLengthSid( owner )))
1655 return STATUS_INVALID_SECURITY_DESCR;
1658 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1660 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1661 if (status != STATUS_SUCCESS) return status;
1662 if (!(sd.group_len = RtlLengthSid( group )))
1663 return STATUS_INVALID_SECURITY_DESCR;
1666 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1668 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1669 if (status != STATUS_SUCCESS) return status;
1670 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1671 sd.control |= SE_SACL_PRESENT;
1674 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1676 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1677 if (status != STATUS_SUCCESS) return status;
1678 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1679 sd.control |= SE_DACL_PRESENT;
1682 SERVER_START_REQ( set_security_object )
1684 req->handle = wine_server_obj_handle( Handle );
1685 req->security_info = SecurityInformation;
1687 wine_server_add_data( req, &sd, sizeof(sd) );
1688 wine_server_add_data( req, owner, sd.owner_len );
1689 wine_server_add_data( req, group, sd.group_len );
1690 wine_server_add_data( req, sacl, sd.sacl_len );
1691 wine_server_add_data( req, dacl, sd.dacl_len );
1692 status = wine_server_call( req );
1694 SERVER_END_REQ;
1696 return status;
1699 /******************************************************************************
1700 * RtlConvertSidToUnicodeString (NTDLL.@)
1702 * The returned SID is used to access the USER registry hive usually
1704 * the native function returns something like
1705 * "S-1-5-21-0000000000-000000000-0000000000-500";
1707 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1708 PUNICODE_STRING String,
1709 PSID pSid,
1710 BOOLEAN AllocateString)
1712 static const WCHAR formatW[] = {'-','%','u',0};
1713 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1714 WCHAR *p = buffer;
1715 const SID *sid = (const SID *)pSid;
1716 DWORD i, len;
1718 *p++ = 'S';
1719 p += sprintfW( p, formatW, sid->Revision );
1720 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1721 sid->IdentifierAuthority.Value[4] ),
1722 MAKEWORD( sid->IdentifierAuthority.Value[3],
1723 sid->IdentifierAuthority.Value[2] )));
1724 for (i = 0; i < sid->SubAuthorityCount; i++)
1725 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1727 len = (p + 1 - buffer) * sizeof(WCHAR);
1729 String->Length = len - sizeof(WCHAR);
1730 if (AllocateString)
1732 String->MaximumLength = len;
1733 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1734 return STATUS_NO_MEMORY;
1736 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1738 memcpy( String->Buffer, buffer, len );
1739 return STATUS_SUCCESS;
1742 /******************************************************************************
1743 * RtlQueryInformationAcl (NTDLL.@)
1745 NTSTATUS WINAPI RtlQueryInformationAcl(
1746 PACL pAcl,
1747 LPVOID pAclInformation,
1748 DWORD nAclInformationLength,
1749 ACL_INFORMATION_CLASS dwAclInformationClass)
1751 NTSTATUS status = STATUS_SUCCESS;
1753 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1754 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1756 switch (dwAclInformationClass)
1758 case AclRevisionInformation:
1760 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1762 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1763 status = STATUS_INVALID_PARAMETER;
1764 else
1765 paclrev->AclRevision = pAcl->AclRevision;
1767 break;
1770 case AclSizeInformation:
1772 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1774 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1775 status = STATUS_INVALID_PARAMETER;
1776 else
1778 paclsize->AceCount = pAcl->AceCount;
1779 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1780 if (pAcl->AclSize < paclsize->AclBytesInUse)
1782 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1783 paclsize->AclBytesFree = 0;
1784 paclsize->AclBytesInUse = pAcl->AclSize;
1786 else
1787 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1790 break;
1793 default:
1794 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1795 status = STATUS_INVALID_PARAMETER;
1798 return status;