push 212f1dad91f15aefd8e676124180e0b86d7c9ee6
[wine/hacks.git] / dlls / ntdll / sec.c
bloba764e2155b4ff6f925cb5f188d80e78a72b19cd4
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);
622 else
624 *pDacl = NULL;
625 *lpbDaclDefaulted = 0;
628 return STATUS_SUCCESS;
631 /**************************************************************************
632 * RtlSetDaclSecurityDescriptor [NTDLL.@]
634 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
635 PSECURITY_DESCRIPTOR pSecurityDescriptor,
636 BOOLEAN daclpresent,
637 PACL dacl,
638 BOOLEAN dacldefaulted )
640 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
642 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
643 return STATUS_UNKNOWN_REVISION;
644 if (lpsd->Control & SE_SELF_RELATIVE)
645 return STATUS_INVALID_SECURITY_DESCR;
647 if (!daclpresent)
649 lpsd->Control &= ~SE_DACL_PRESENT;
650 return STATUS_SUCCESS;
653 lpsd->Control |= SE_DACL_PRESENT;
654 lpsd->Dacl = dacl;
656 if (dacldefaulted)
657 lpsd->Control |= SE_DACL_DEFAULTED;
658 else
659 lpsd->Control &= ~SE_DACL_DEFAULTED;
661 return STATUS_SUCCESS;
664 /******************************************************************************
665 * RtlGetSaclSecurityDescriptor [NTDLL.@]
668 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
669 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
670 OUT PBOOLEAN lpbSaclPresent,
671 OUT PACL *pSacl,
672 OUT PBOOLEAN lpbSaclDefaulted)
674 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
676 TRACE("(%p,%p,%p,%p)\n",
677 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
679 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
680 return STATUS_UNKNOWN_REVISION;
682 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
684 if (SE_SELF_RELATIVE & lpsd->Control)
685 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
686 else
687 *pSacl = lpsd->Sacl;
689 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
692 return STATUS_SUCCESS;
695 /**************************************************************************
696 * RtlSetSaclSecurityDescriptor [NTDLL.@]
698 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
699 PSECURITY_DESCRIPTOR pSecurityDescriptor,
700 BOOLEAN saclpresent,
701 PACL sacl,
702 BOOLEAN sacldefaulted)
704 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
706 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
707 return STATUS_UNKNOWN_REVISION;
708 if (lpsd->Control & SE_SELF_RELATIVE)
709 return STATUS_INVALID_SECURITY_DESCR;
710 if (!saclpresent) {
711 lpsd->Control &= ~SE_SACL_PRESENT;
712 return 0;
714 lpsd->Control |= SE_SACL_PRESENT;
715 lpsd->Sacl = sacl;
716 if (sacldefaulted)
717 lpsd->Control |= SE_SACL_DEFAULTED;
718 else
719 lpsd->Control &= ~SE_SACL_DEFAULTED;
720 return STATUS_SUCCESS;
723 /**************************************************************************
724 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
726 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
727 PSECURITY_DESCRIPTOR pSecurityDescriptor,
728 PSID *Owner,
729 PBOOLEAN OwnerDefaulted)
731 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
733 if ( !lpsd || !Owner || !OwnerDefaulted )
734 return STATUS_INVALID_PARAMETER;
736 if ( lpsd->Control & SE_OWNER_DEFAULTED )
737 *OwnerDefaulted = TRUE;
738 else
739 *OwnerDefaulted = FALSE;
741 if (lpsd->Owner != NULL)
743 if (lpsd->Control & SE_SELF_RELATIVE)
744 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
745 else
746 *Owner = lpsd->Owner;
749 else
750 *Owner = NULL;
752 return STATUS_SUCCESS;
755 /**************************************************************************
756 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
758 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
759 PSECURITY_DESCRIPTOR pSecurityDescriptor,
760 PSID owner,
761 BOOLEAN ownerdefaulted)
763 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
765 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
766 return STATUS_UNKNOWN_REVISION;
767 if (lpsd->Control & SE_SELF_RELATIVE)
768 return STATUS_INVALID_SECURITY_DESCR;
770 lpsd->Owner = owner;
771 if (ownerdefaulted)
772 lpsd->Control |= SE_OWNER_DEFAULTED;
773 else
774 lpsd->Control &= ~SE_OWNER_DEFAULTED;
775 return STATUS_SUCCESS;
778 /**************************************************************************
779 * RtlSetGroupSecurityDescriptor [NTDLL.@]
781 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
782 PSECURITY_DESCRIPTOR pSecurityDescriptor,
783 PSID group,
784 BOOLEAN groupdefaulted)
786 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
788 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
789 return STATUS_UNKNOWN_REVISION;
790 if (lpsd->Control & SE_SELF_RELATIVE)
791 return STATUS_INVALID_SECURITY_DESCR;
793 lpsd->Group = group;
794 if (groupdefaulted)
795 lpsd->Control |= SE_GROUP_DEFAULTED;
796 else
797 lpsd->Control &= ~SE_GROUP_DEFAULTED;
798 return STATUS_SUCCESS;
801 /**************************************************************************
802 * RtlGetGroupSecurityDescriptor [NTDLL.@]
804 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
805 PSECURITY_DESCRIPTOR pSecurityDescriptor,
806 PSID *Group,
807 PBOOLEAN GroupDefaulted)
809 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
811 if ( !lpsd || !Group || !GroupDefaulted )
812 return STATUS_INVALID_PARAMETER;
814 if ( lpsd->Control & SE_GROUP_DEFAULTED )
815 *GroupDefaulted = TRUE;
816 else
817 *GroupDefaulted = FALSE;
819 if (lpsd->Group != NULL)
821 if (lpsd->Control & SE_SELF_RELATIVE)
822 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
823 else
824 *Group = lpsd->Group;
826 else
827 *Group = NULL;
829 return STATUS_SUCCESS;
832 /**************************************************************************
833 * RtlMakeSelfRelativeSD [NTDLL.@]
835 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
836 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
837 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
838 IN OUT LPDWORD lpdwBufferLength)
840 ULONG_PTR offsetRel;
841 ULONG length;
842 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
843 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
845 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
846 lpdwBufferLength ? *lpdwBufferLength: -1);
848 if (!lpdwBufferLength || !pAbs)
849 return STATUS_INVALID_PARAMETER;
851 length = RtlLengthSecurityDescriptor(pAbs);
852 if (*lpdwBufferLength < length)
854 *lpdwBufferLength = length;
855 return STATUS_BUFFER_TOO_SMALL;
858 if (!pRel)
859 return STATUS_INVALID_PARAMETER;
861 if (pAbs->Control & SE_SELF_RELATIVE)
863 memcpy(pRel, pAbs, length);
864 return STATUS_SUCCESS;
867 pRel->Revision = pAbs->Revision;
868 pRel->Sbz1 = pAbs->Sbz1;
869 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
871 offsetRel = sizeof(SECURITY_DESCRIPTOR);
872 if (pAbs->Owner)
874 pRel->Owner = (PSID) offsetRel;
875 length = RtlLengthSid(pAbs->Owner);
876 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
877 offsetRel += length;
879 else
881 pRel->Owner = NULL;
884 if (pAbs->Group)
886 pRel->Group = (PSID) offsetRel;
887 length = RtlLengthSid(pAbs->Group);
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
889 offsetRel += length;
891 else
893 pRel->Group = NULL;
896 if (pAbs->Sacl)
898 pRel->Sacl = (PACL) offsetRel;
899 length = pAbs->Sacl->AclSize;
900 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
901 offsetRel += length;
903 else
905 pRel->Sacl = NULL;
908 if (pAbs->Dacl)
910 pRel->Dacl = (PACL) offsetRel;
911 length = pAbs->Dacl->AclSize;
912 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
914 else
916 pRel->Dacl = NULL;
919 return STATUS_SUCCESS;
923 /**************************************************************************
924 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
926 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
927 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
928 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
929 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
930 OUT PACL pDacl,
931 OUT LPDWORD lpdwDaclSize,
932 OUT PACL pSacl,
933 OUT LPDWORD lpdwSaclSize,
934 OUT PSID pOwner,
935 OUT LPDWORD lpdwOwnerSize,
936 OUT PSID pPrimaryGroup,
937 OUT LPDWORD lpdwPrimaryGroupSize)
939 NTSTATUS status = STATUS_SUCCESS;
940 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
941 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
943 if (!pRel ||
944 !lpdwAbsoluteSecurityDescriptorSize ||
945 !lpdwDaclSize ||
946 !lpdwSaclSize ||
947 !lpdwOwnerSize ||
948 !lpdwPrimaryGroupSize ||
949 ~pRel->Control & SE_SELF_RELATIVE)
950 return STATUS_INVALID_PARAMETER;
952 /* Confirm buffers are sufficiently large */
953 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
955 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
956 status = STATUS_BUFFER_TOO_SMALL;
959 if (pRel->Control & SE_DACL_PRESENT &&
960 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
962 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
963 status = STATUS_BUFFER_TOO_SMALL;
966 if (pRel->Control & SE_SACL_PRESENT &&
967 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
969 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
970 status = STATUS_BUFFER_TOO_SMALL;
973 if (pRel->Owner &&
974 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
976 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
977 status = STATUS_BUFFER_TOO_SMALL;
980 if (pRel->Group &&
981 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
983 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
984 status = STATUS_BUFFER_TOO_SMALL;
987 if (status != STATUS_SUCCESS)
988 return status;
990 /* Copy structures, and clear the ones we don't set */
991 pAbs->Revision = pRel->Revision;
992 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
993 pAbs->Sacl = NULL;
994 pAbs->Dacl = NULL;
995 pAbs->Owner = NULL;
996 pAbs->Group = NULL;
998 if (pRel->Control & SE_SACL_PRESENT)
1000 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
1002 memcpy(pSacl, pAcl, pAcl->AclSize);
1003 pAbs->Sacl = pSacl;
1006 if (pRel->Control & SE_DACL_PRESENT)
1008 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1009 memcpy(pDacl, pAcl, pAcl->AclSize);
1010 pAbs->Dacl = pDacl;
1013 if (pRel->Owner)
1015 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1016 memcpy(pOwner, psid, RtlLengthSid(psid));
1017 pAbs->Owner = pOwner;
1020 if (pRel->Group)
1022 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1023 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1024 pAbs->Group = pPrimaryGroup;
1027 return status;
1030 /******************************************************************************
1031 * RtlGetControlSecurityDescriptor (NTDLL.@)
1033 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1034 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1035 PSECURITY_DESCRIPTOR_CONTROL pControl,
1036 LPDWORD lpdwRevision)
1038 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1040 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1042 *lpdwRevision = lpsd->Revision;
1044 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1045 return STATUS_UNKNOWN_REVISION;
1047 *pControl = lpsd->Control;
1049 return STATUS_SUCCESS;
1052 /******************************************************************************
1053 * RtlSetControlSecurityDescriptor (NTDLL.@)
1055 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1056 PSECURITY_DESCRIPTOR SecurityDescriptor,
1057 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1058 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1060 SECURITY_DESCRIPTOR_CONTROL const immutable
1061 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1062 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1063 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1064 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1067 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1069 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1070 ControlBitsOfInterest, ControlBitsToSet);
1072 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1073 return STATUS_INVALID_PARAMETER;
1075 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1076 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1078 return STATUS_SUCCESS;
1082 /**************************************************************************
1083 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1085 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1086 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1087 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1088 PULONG BufferLength)
1090 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1092 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1093 SelfRelativeSecurityDescriptor, BufferLength);
1095 if (abs->Control & SE_SELF_RELATIVE)
1096 return STATUS_BAD_DESCRIPTOR_FORMAT;
1098 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1099 SelfRelativeSecurityDescriptor, BufferLength);
1104 * access control list's
1107 /**************************************************************************
1108 * RtlCreateAcl [NTDLL.@]
1110 * NOTES
1111 * This should return NTSTATUS
1113 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1115 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1117 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1118 return STATUS_INVALID_PARAMETER;
1119 if (size<sizeof(ACL))
1120 return STATUS_BUFFER_TOO_SMALL;
1121 if (size>0xFFFF)
1122 return STATUS_INVALID_PARAMETER;
1124 memset(acl,'\0',sizeof(ACL));
1125 acl->AclRevision = rev;
1126 acl->AclSize = size;
1127 acl->AceCount = 0;
1128 return STATUS_SUCCESS;
1131 /**************************************************************************
1132 * RtlFirstFreeAce [NTDLL.@]
1133 * looks for the AceCount+1 ACE, and if it is still within the alloced
1134 * ACL, return a pointer to it
1136 BOOLEAN WINAPI RtlFirstFreeAce(
1137 PACL acl,
1138 PACE_HEADER *x)
1140 PACE_HEADER ace;
1141 int i;
1143 *x = 0;
1144 ace = (PACE_HEADER)(acl+1);
1145 for (i=0;i<acl->AceCount;i++) {
1146 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1147 return 0;
1148 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1150 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1151 return 0;
1152 *x = ace;
1153 return 1;
1156 /**************************************************************************
1157 * RtlAddAce [NTDLL.@]
1159 NTSTATUS WINAPI RtlAddAce(
1160 PACL acl,
1161 DWORD rev,
1162 DWORD xnrofaces,
1163 PACE_HEADER acestart,
1164 DWORD acelen)
1166 PACE_HEADER ace,targetace;
1167 int nrofaces;
1169 if (acl->AclRevision != ACL_REVISION)
1170 return STATUS_INVALID_PARAMETER;
1171 if (!RtlFirstFreeAce(acl,&targetace))
1172 return STATUS_INVALID_PARAMETER;
1173 nrofaces=0;ace=acestart;
1174 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1175 nrofaces++;
1176 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1178 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1179 return STATUS_INVALID_PARAMETER;
1180 memcpy((LPBYTE)targetace,acestart,acelen);
1181 acl->AceCount+=nrofaces;
1182 return STATUS_SUCCESS;
1185 /**************************************************************************
1186 * RtlDeleteAce [NTDLL.@]
1188 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1190 NTSTATUS status;
1191 PACE_HEADER pAce;
1193 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1195 if (STATUS_SUCCESS == status)
1197 PACE_HEADER pcAce;
1198 DWORD len = 0;
1200 /* skip over the ACE we are deleting */
1201 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1202 dwAceIndex++;
1204 /* calculate the length of the rest */
1205 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1207 len += pcAce->AceSize;
1208 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1211 /* slide them all backwards */
1212 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1213 pAcl->AceCount--;
1216 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1218 return status;
1221 /******************************************************************************
1222 * RtlAddAccessAllowedAce [NTDLL.@]
1224 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1225 IN OUT PACL pAcl,
1226 IN DWORD dwAceRevision,
1227 IN DWORD AccessMask,
1228 IN PSID pSid)
1230 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1233 /******************************************************************************
1234 * RtlAddAccessAllowedAceEx [NTDLL.@]
1236 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1237 IN OUT PACL pAcl,
1238 IN DWORD dwAceRevision,
1239 IN DWORD AceFlags,
1240 IN DWORD AccessMask,
1241 IN PSID pSid)
1243 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1245 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1246 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1249 /******************************************************************************
1250 * RtlAddAccessDeniedAce [NTDLL.@]
1252 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1253 IN OUT PACL pAcl,
1254 IN DWORD dwAceRevision,
1255 IN DWORD AccessMask,
1256 IN PSID pSid)
1258 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1261 /******************************************************************************
1262 * RtlAddAccessDeniedAceEx [NTDLL.@]
1264 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1265 IN OUT PACL pAcl,
1266 IN DWORD dwAceRevision,
1267 IN DWORD AceFlags,
1268 IN DWORD AccessMask,
1269 IN PSID pSid)
1271 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1273 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1274 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1277 /**************************************************************************
1278 * RtlAddAuditAccessAce [NTDLL.@]
1280 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1281 IN OUT PACL pAcl,
1282 IN DWORD dwAceRevision,
1283 IN DWORD dwAceFlags,
1284 IN DWORD dwAccessMask,
1285 IN PSID pSid,
1286 IN BOOL bAuditSuccess,
1287 IN BOOL bAuditFailure)
1289 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1290 pSid,bAuditSuccess,bAuditFailure);
1292 if (bAuditSuccess)
1293 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1295 if (bAuditFailure)
1296 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1298 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1299 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1302 /**************************************************************************
1303 * RtlAddAuditAccessAce [NTDLL.@]
1305 NTSTATUS WINAPI RtlAddAuditAccessAce(
1306 IN OUT PACL pAcl,
1307 IN DWORD dwAceRevision,
1308 IN DWORD dwAccessMask,
1309 IN PSID pSid,
1310 IN BOOL bAuditSuccess,
1311 IN BOOL bAuditFailure)
1313 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1316 /******************************************************************************
1317 * RtlValidAcl [NTDLL.@]
1319 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1321 BOOLEAN ret;
1322 TRACE("(%p)\n", pAcl);
1324 __TRY
1326 PACE_HEADER ace;
1327 int i;
1329 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1330 pAcl->AclRevision > MAX_ACL_REVISION)
1331 ret = FALSE;
1332 else
1334 ace = (PACE_HEADER)(pAcl+1);
1335 ret = TRUE;
1336 for (i=0;i<=pAcl->AceCount;i++)
1338 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1340 ret = FALSE;
1341 break;
1343 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1347 __EXCEPT_PAGE_FAULT
1349 WARN("(%p): invalid pointer!\n", pAcl);
1350 return 0;
1352 __ENDTRY
1353 return ret;
1356 /******************************************************************************
1357 * RtlGetAce [NTDLL.@]
1359 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1361 PACE_HEADER ace;
1363 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1365 if (dwAceIndex >= pAcl->AceCount)
1366 return STATUS_INVALID_PARAMETER;
1368 ace = (PACE_HEADER)(pAcl + 1);
1369 for (;dwAceIndex;dwAceIndex--)
1370 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1372 *pAce = (LPVOID) ace;
1374 return STATUS_SUCCESS;
1378 * misc
1381 /******************************************************************************
1382 * RtlAdjustPrivilege [NTDLL.@]
1384 * Enables or disables a privilege from the calling thread or process.
1386 * PARAMS
1387 * Privilege [I] Privilege index to change.
1388 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1389 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1390 * Enabled [O] Whether privilege was previously enabled or disabled.
1392 * RETURNS
1393 * Success: STATUS_SUCCESS.
1394 * Failure: NTSTATUS code.
1396 * SEE ALSO
1397 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1400 NTSTATUS WINAPI
1401 RtlAdjustPrivilege(ULONG Privilege,
1402 BOOLEAN Enable,
1403 BOOLEAN CurrentThread,
1404 PBOOLEAN Enabled)
1406 TOKEN_PRIVILEGES NewState;
1407 TOKEN_PRIVILEGES OldState;
1408 ULONG ReturnLength;
1409 HANDLE TokenHandle;
1410 NTSTATUS Status;
1412 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1413 CurrentThread ? "TRUE" : "FALSE", Enabled);
1415 if (CurrentThread)
1417 Status = NtOpenThreadToken(GetCurrentThread(),
1418 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1419 FALSE,
1420 &TokenHandle);
1422 else
1424 Status = NtOpenProcessToken(GetCurrentProcess(),
1425 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1426 &TokenHandle);
1429 if (!NT_SUCCESS(Status))
1431 WARN("Retrieving token handle failed (Status %x)\n", Status);
1432 return Status;
1435 OldState.PrivilegeCount = 1;
1437 NewState.PrivilegeCount = 1;
1438 NewState.Privileges[0].Luid.LowPart = Privilege;
1439 NewState.Privileges[0].Luid.HighPart = 0;
1440 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1442 Status = NtAdjustPrivilegesToken(TokenHandle,
1443 FALSE,
1444 &NewState,
1445 sizeof(TOKEN_PRIVILEGES),
1446 &OldState,
1447 &ReturnLength);
1448 NtClose (TokenHandle);
1449 if (Status == STATUS_NOT_ALL_ASSIGNED)
1451 TRACE("Failed to assign all privileges\n");
1452 return STATUS_PRIVILEGE_NOT_HELD;
1454 if (!NT_SUCCESS(Status))
1456 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1457 return Status;
1460 if (OldState.PrivilegeCount == 0)
1461 *Enabled = Enable;
1462 else
1463 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1465 return STATUS_SUCCESS;
1468 /******************************************************************************
1469 * RtlImpersonateSelf [NTDLL.@]
1471 * Makes an impersonation token that represents the process user and assigns
1472 * to the current thread.
1474 * PARAMS
1475 * ImpersonationLevel [I] Level at which to impersonate.
1477 * RETURNS
1478 * Success: STATUS_SUCCESS.
1479 * Failure: NTSTATUS code.
1481 NTSTATUS WINAPI
1482 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1484 NTSTATUS Status;
1485 OBJECT_ATTRIBUTES ObjectAttributes;
1486 HANDLE ProcessToken;
1487 HANDLE ImpersonationToken;
1489 TRACE("(%08x)\n", ImpersonationLevel);
1491 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1492 &ProcessToken);
1493 if (Status != STATUS_SUCCESS)
1494 return Status;
1496 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1498 Status = NtDuplicateToken( ProcessToken,
1499 TOKEN_IMPERSONATE,
1500 &ObjectAttributes,
1501 ImpersonationLevel,
1502 TokenImpersonation,
1503 &ImpersonationToken );
1504 if (Status != STATUS_SUCCESS)
1506 NtClose( ProcessToken );
1507 return Status;
1510 Status = NtSetInformationThread( GetCurrentThread(),
1511 ThreadImpersonationToken,
1512 &ImpersonationToken,
1513 sizeof(ImpersonationToken) );
1515 NtClose( ImpersonationToken );
1516 NtClose( ProcessToken );
1518 return Status;
1521 /******************************************************************************
1522 * NtAccessCheck [NTDLL.@]
1523 * ZwAccessCheck [NTDLL.@]
1525 * Checks that a user represented by a token is allowed to access an object
1526 * represented by a security descriptor.
1528 * PARAMS
1529 * SecurityDescriptor [I] The security descriptor of the object to check.
1530 * ClientToken [I] Token of the user accessing the object.
1531 * DesiredAccess [I] The desired access to the object.
1532 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1533 * PrivilegeSet [I/O] Privileges used during the access check.
1534 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1535 * GrantedAccess [O] The actual access rights granted.
1536 * AccessStatus [O] The status of the access check.
1538 * RETURNS
1539 * NTSTATUS code.
1541 * NOTES
1542 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1543 * the maximum access rights allowed by the SD and returns them in
1544 * GrantedAccess.
1545 * The SecurityDescriptor must have a valid owner and groups present,
1546 * otherwise the function will fail.
1548 NTSTATUS WINAPI
1549 NtAccessCheck(
1550 PSECURITY_DESCRIPTOR SecurityDescriptor,
1551 HANDLE ClientToken,
1552 ACCESS_MASK DesiredAccess,
1553 PGENERIC_MAPPING GenericMapping,
1554 PPRIVILEGE_SET PrivilegeSet,
1555 PULONG ReturnLength,
1556 PULONG GrantedAccess,
1557 NTSTATUS *AccessStatus)
1559 NTSTATUS status;
1561 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1562 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1563 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1565 SERVER_START_REQ( access_check )
1567 struct security_descriptor sd;
1568 PSID owner;
1569 PSID group;
1570 PACL sacl;
1571 PACL dacl;
1572 BOOLEAN defaulted, present;
1573 DWORD revision;
1574 SECURITY_DESCRIPTOR_CONTROL control;
1576 req->handle = wine_server_obj_handle( ClientToken );
1577 req->desired_access = DesiredAccess;
1578 req->mapping_read = GenericMapping->GenericRead;
1579 req->mapping_write = GenericMapping->GenericWrite;
1580 req->mapping_execute = GenericMapping->GenericExecute;
1581 req->mapping_all = GenericMapping->GenericAll;
1583 /* marshal security descriptor */
1584 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1585 sd.control = control & ~SE_SELF_RELATIVE;
1586 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1587 sd.owner_len = RtlLengthSid( owner );
1588 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1589 sd.group_len = RtlLengthSid( group );
1590 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1591 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1592 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1593 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1595 wine_server_add_data( req, &sd, sizeof(sd) );
1596 wine_server_add_data( req, owner, sd.owner_len );
1597 wine_server_add_data( req, group, sd.group_len );
1598 wine_server_add_data( req, sacl, sd.sacl_len );
1599 wine_server_add_data( req, dacl, sd.dacl_len );
1601 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1603 status = wine_server_call( req );
1605 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1606 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1608 if (status == STATUS_SUCCESS)
1610 *AccessStatus = reply->access_status;
1611 *GrantedAccess = reply->access_granted;
1614 SERVER_END_REQ;
1616 return status;
1619 /******************************************************************************
1620 * NtSetSecurityObject [NTDLL.@]
1621 * ZwSetSecurityObject [NTDLL.@]
1623 * Sets specified parts of the object's security descriptor.
1625 * PARAMS
1626 * Handle [I] Handle to the object to change security descriptor of.
1627 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1628 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1630 * RETURNS
1631 * NTSTATUS code.
1634 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1635 SECURITY_INFORMATION SecurityInformation,
1636 PSECURITY_DESCRIPTOR SecurityDescriptor)
1638 NTSTATUS status;
1639 struct security_descriptor sd;
1640 PACL dacl = NULL, sacl = NULL;
1641 PSID owner = NULL, group = NULL;
1642 BOOLEAN defaulted, present;
1643 DWORD revision;
1644 SECURITY_DESCRIPTOR_CONTROL control;
1646 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1648 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1650 memset( &sd, 0, sizeof(sd) );
1651 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1652 if (status != STATUS_SUCCESS) return status;
1653 sd.control = control & ~SE_SELF_RELATIVE;
1655 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1657 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1658 if (status != STATUS_SUCCESS) return status;
1659 if (!(sd.owner_len = RtlLengthSid( owner )))
1660 return STATUS_INVALID_SECURITY_DESCR;
1663 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1665 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1666 if (status != STATUS_SUCCESS) return status;
1667 if (!(sd.group_len = RtlLengthSid( group )))
1668 return STATUS_INVALID_SECURITY_DESCR;
1671 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1673 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1674 if (status != STATUS_SUCCESS) return status;
1675 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1676 sd.control |= SE_SACL_PRESENT;
1679 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1681 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1682 if (status != STATUS_SUCCESS) return status;
1683 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1684 sd.control |= SE_DACL_PRESENT;
1687 SERVER_START_REQ( set_security_object )
1689 req->handle = wine_server_obj_handle( Handle );
1690 req->security_info = SecurityInformation;
1692 wine_server_add_data( req, &sd, sizeof(sd) );
1693 wine_server_add_data( req, owner, sd.owner_len );
1694 wine_server_add_data( req, group, sd.group_len );
1695 wine_server_add_data( req, sacl, sd.sacl_len );
1696 wine_server_add_data( req, dacl, sd.dacl_len );
1697 status = wine_server_call( req );
1699 SERVER_END_REQ;
1701 return status;
1704 /******************************************************************************
1705 * RtlConvertSidToUnicodeString (NTDLL.@)
1707 * The returned SID is used to access the USER registry hive usually
1709 * the native function returns something like
1710 * "S-1-5-21-0000000000-000000000-0000000000-500";
1712 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1713 PUNICODE_STRING String,
1714 PSID pSid,
1715 BOOLEAN AllocateString)
1717 static const WCHAR formatW[] = {'-','%','u',0};
1718 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1719 WCHAR *p = buffer;
1720 const SID *sid = (const SID *)pSid;
1721 DWORD i, len;
1723 *p++ = 'S';
1724 p += sprintfW( p, formatW, sid->Revision );
1725 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1726 sid->IdentifierAuthority.Value[4] ),
1727 MAKEWORD( sid->IdentifierAuthority.Value[3],
1728 sid->IdentifierAuthority.Value[2] )));
1729 for (i = 0; i < sid->SubAuthorityCount; i++)
1730 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1732 len = (p + 1 - buffer) * sizeof(WCHAR);
1734 String->Length = len - sizeof(WCHAR);
1735 if (AllocateString)
1737 String->MaximumLength = len;
1738 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1739 return STATUS_NO_MEMORY;
1741 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1743 memcpy( String->Buffer, buffer, len );
1744 return STATUS_SUCCESS;
1747 /******************************************************************************
1748 * RtlQueryInformationAcl (NTDLL.@)
1750 NTSTATUS WINAPI RtlQueryInformationAcl(
1751 PACL pAcl,
1752 LPVOID pAclInformation,
1753 DWORD nAclInformationLength,
1754 ACL_INFORMATION_CLASS dwAclInformationClass)
1756 NTSTATUS status = STATUS_SUCCESS;
1758 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1759 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1761 switch (dwAclInformationClass)
1763 case AclRevisionInformation:
1765 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1767 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1768 status = STATUS_INVALID_PARAMETER;
1769 else
1770 paclrev->AclRevision = pAcl->AclRevision;
1772 break;
1775 case AclSizeInformation:
1777 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1779 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1780 status = STATUS_INVALID_PARAMETER;
1781 else
1783 paclsize->AceCount = pAcl->AceCount;
1784 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1785 if (pAcl->AclSize < paclsize->AclBytesInUse)
1787 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1788 paclsize->AclBytesFree = 0;
1789 paclsize->AclBytesInUse = pAcl->AclSize;
1791 else
1792 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1795 break;
1798 default:
1799 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1800 status = STATUS_INVALID_PARAMETER;
1803 return status;