ntdll: Fix RtlValidAcl to accept newer ACL revisions.
[wine/multimedia.git] / dlls / ntdll / sec.c
bloba1c839dca2b9d36983cb011c7b51908bd9096e2a
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 "wine/exception.h"
39 #include "ntdll_misc.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 copy an ACL */
49 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
51 DWORD size;
53 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
54 return FALSE;
56 size = ((ACL *)pSourceAcl)->AclSize;
57 if (nDestinationAclLength < size)
58 return FALSE;
60 memmove(pDestinationAcl, pSourceAcl, size);
61 return TRUE;
64 /* generically adds an ACE to an ACL */
65 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
66 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
68 ACE_HEADER *pAceHeader;
69 DWORD dwLengthSid;
70 DWORD dwAceSize;
71 DWORD *pAccessMask;
72 DWORD *pSidStart;
74 if (!RtlValidSid(pSid))
75 return STATUS_INVALID_SID;
77 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
78 return STATUS_REVISION_MISMATCH;
80 if (!RtlValidAcl(pAcl))
81 return STATUS_INVALID_ACL;
83 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
84 return STATUS_INVALID_ACL;
86 if (!pAceHeader)
87 return STATUS_ALLOTTED_SPACE_EXCEEDED;
89 /* calculate generic size of the ACE */
90 dwLengthSid = RtlLengthSid(pSid);
91 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
92 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
93 return STATUS_ALLOTTED_SPACE_EXCEEDED;
95 /* fill the new ACE */
96 pAceHeader->AceType = dwAceType;
97 pAceHeader->AceFlags = dwAceFlags;
98 pAceHeader->AceSize = dwAceSize;
100 /* skip past the ACE_HEADER of the ACE */
101 pAccessMask = (DWORD *)(pAceHeader + 1);
102 *pAccessMask = dwAccessMask;
104 /* skip past ACE->Mask */
105 pSidStart = pAccessMask + 1;
106 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
108 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
109 pAcl->AceCount++;
111 return STATUS_SUCCESS;
115 * SID FUNCTIONS
118 /******************************************************************************
119 * RtlAllocateAndInitializeSid [NTDLL.@]
122 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
123 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
124 BYTE nSubAuthorityCount,
125 DWORD nSubAuthority0, DWORD nSubAuthority1,
126 DWORD nSubAuthority2, DWORD nSubAuthority3,
127 DWORD nSubAuthority4, DWORD nSubAuthority5,
128 DWORD nSubAuthority6, DWORD nSubAuthority7,
129 PSID *pSid )
131 SID *tmp_sid;
133 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
134 pIdentifierAuthority,nSubAuthorityCount,
135 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
136 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
138 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
140 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
141 RtlLengthRequiredSid(nSubAuthorityCount))))
142 return STATUS_NO_MEMORY;
144 tmp_sid->Revision = SID_REVISION;
146 if (pIdentifierAuthority)
147 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
148 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
150 switch( nSubAuthorityCount )
152 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
153 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
154 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
155 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
156 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
157 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
158 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
159 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
160 break;
162 *pSid = tmp_sid;
163 return STATUS_SUCCESS;
166 /******************************************************************************
167 * RtlEqualSid [NTDLL.@]
169 * Determine if two SIDs are equal.
171 * PARAMS
172 * pSid1 [I] Source SID
173 * pSid2 [I] SID to compare with
175 * RETURNS
176 * TRUE, if pSid1 is equal to pSid2,
177 * FALSE otherwise.
179 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
181 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
182 return FALSE;
184 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
185 return FALSE;
187 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
188 return FALSE;
190 return TRUE;
193 /******************************************************************************
194 * RtlEqualPrefixSid [NTDLL.@]
196 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
198 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
199 return FALSE;
201 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
202 return FALSE;
204 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
205 return FALSE;
207 return TRUE;
211 /******************************************************************************
212 * RtlFreeSid [NTDLL.@]
214 * Free the resources used by a SID.
216 * PARAMS
217 * pSid [I] SID to Free.
219 * RETURNS
220 * STATUS_SUCCESS.
222 DWORD WINAPI RtlFreeSid(PSID pSid)
224 TRACE("(%p)\n", pSid);
225 RtlFreeHeap( GetProcessHeap(), 0, pSid );
226 return STATUS_SUCCESS;
229 /**************************************************************************
230 * RtlLengthRequiredSid [NTDLL.@]
232 * Determine the amount of memory a SID will use
234 * PARAMS
235 * nrofsubauths [I] Number of Sub Authorities in the SID.
237 * RETURNS
238 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
240 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
242 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
245 /**************************************************************************
246 * RtlLengthSid [NTDLL.@]
248 * Determine the amount of memory a SID is using
250 * PARAMS
251 * pSid [I] SID to get the size of.
253 * RETURNS
254 * The size, in bytes, of pSid.
256 DWORD WINAPI RtlLengthSid(PSID pSid)
258 TRACE("sid=%p\n",pSid);
259 if (!pSid) return 0;
260 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
263 /**************************************************************************
264 * RtlInitializeSid [NTDLL.@]
266 * Initialise a SID.
268 * PARAMS
269 * pSid [I] SID to initialise
270 * pIdentifierAuthority [I] Identifier Authority
271 * nSubAuthorityCount [I] Number of Sub Authorities
273 * RETURNS
274 * Success: TRUE. pSid is initialised with the details given.
275 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
277 BOOL WINAPI RtlInitializeSid(
278 PSID pSid,
279 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
280 BYTE nSubAuthorityCount)
282 int i;
283 SID* pisid=pSid;
285 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
286 return FALSE;
288 pisid->Revision = SID_REVISION;
289 pisid->SubAuthorityCount = nSubAuthorityCount;
290 if (pIdentifierAuthority)
291 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
293 for (i = 0; i < nSubAuthorityCount; i++)
294 *RtlSubAuthoritySid(pSid, i) = 0;
296 return TRUE;
299 /**************************************************************************
300 * RtlSubAuthoritySid [NTDLL.@]
302 * Return the Sub Authority of a SID
304 * PARAMS
305 * pSid [I] SID to get the Sub Authority from.
306 * nSubAuthority [I] Sub Authority number.
308 * RETURNS
309 * A pointer to The Sub Authority value of pSid.
311 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
313 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
316 /**************************************************************************
317 * RtlIdentifierAuthoritySid [NTDLL.@]
319 * Return the Identifier Authority of a SID.
321 * PARAMS
322 * pSid [I] SID to get the Identifier Authority from.
324 * RETURNS
325 * A pointer to the Identifier Authority value of pSid.
327 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
329 return &(((SID*)pSid)->IdentifierAuthority);
332 /**************************************************************************
333 * RtlSubAuthorityCountSid [NTDLL.@]
335 * Get the number of Sub Authorities in a SID.
337 * PARAMS
338 * pSid [I] SID to get the count from.
340 * RETURNS
341 * A pointer to the Sub Authority count of pSid.
343 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
345 return &(((SID*)pSid)->SubAuthorityCount);
348 /**************************************************************************
349 * RtlCopySid [NTDLL.@]
351 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
353 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
354 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
355 return FALSE;
357 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
358 return FALSE;
360 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
361 return TRUE;
363 /******************************************************************************
364 * RtlValidSid [NTDLL.@]
366 * Determine if a SID is valid.
368 * PARAMS
369 * pSid [I] SID to check
371 * RETURNS
372 * TRUE if pSid is valid,
373 * FALSE otherwise.
375 BOOLEAN WINAPI RtlValidSid( PSID pSid )
377 BOOL ret;
378 __TRY
380 ret = TRUE;
381 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
382 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
384 ret = FALSE;
387 __EXCEPT_PAGE_FAULT
389 WARN("(%p): invalid pointer!\n", pSid);
390 return FALSE;
392 __ENDTRY
393 return ret;
398 * security descriptor functions
401 /**************************************************************************
402 * RtlCreateSecurityDescriptor [NTDLL.@]
404 * Initialise a SECURITY_DESCRIPTOR.
406 * PARAMS
407 * lpsd [O] Descriptor to initialise.
408 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
410 * RETURNS
411 * Success: STATUS_SUCCESS.
412 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
414 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
415 PSECURITY_DESCRIPTOR lpsd,
416 DWORD rev)
418 if (rev!=SECURITY_DESCRIPTOR_REVISION)
419 return STATUS_UNKNOWN_REVISION;
420 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
421 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
422 return STATUS_SUCCESS;
425 /**************************************************************************
426 * RtlCopySecurityDescriptor [NTDLL.@]
428 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
430 * PARAMS
431 * pSourceSD [O] SD to copy from.
432 * pDestinationSD [I] Destination SD.
434 * RETURNS
435 * Success: STATUS_SUCCESS.
436 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
438 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
440 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
441 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
442 PSID Owner, Group;
443 PACL Dacl, Sacl;
444 BOOLEAN defaulted, present;
445 DWORD length;
446 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
448 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
449 return STATUS_UNKNOWN_REVISION;
451 /* copy initial data */
452 destSD->Revision = srcSD->Revision;
453 destSD->Sbz1 = srcSD->Sbz1;
454 destSD->Control = srcSD->Control;
456 /* copy Owner */
457 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
458 length = RtlLengthSid(Owner);
460 if (isSelfRelative)
462 destSD->Owner = srcSD->Owner;
463 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
465 else
467 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
468 RtlCopySid(length, destSD->Owner, Owner);
471 /* copy Group */
472 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
473 length = RtlLengthSid(Group);
475 if (isSelfRelative)
477 destSD->Group = srcSD->Group;
478 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
480 else
482 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
483 RtlCopySid(length, destSD->Group, Group);
486 /* copy Dacl */
487 if (srcSD->Control & SE_DACL_PRESENT)
489 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
490 length = Dacl->AclSize;
492 if (isSelfRelative)
494 destSD->Dacl = srcSD->Dacl;
495 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
497 else
499 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
500 copy_acl(length, destSD->Dacl, Dacl);
504 /* copy Sacl */
505 if (srcSD->Control & SE_SACL_PRESENT)
507 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
508 length = Sacl->AclSize;
510 if (isSelfRelative)
512 destSD->Sacl = srcSD->Sacl;
513 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
515 else
517 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 copy_acl(length, destSD->Sacl, Sacl);
522 return STATUS_SUCCESS;
525 /**************************************************************************
526 * RtlValidSecurityDescriptor [NTDLL.@]
528 * Determine if a SECURITY_DESCRIPTOR is valid.
530 * PARAMS
531 * SecurityDescriptor [I] Descriptor to check.
533 * RETURNS
534 * Success: STATUS_SUCCESS.
535 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
537 NTSTATUS WINAPI RtlValidSecurityDescriptor(
538 PSECURITY_DESCRIPTOR SecurityDescriptor)
540 if ( ! SecurityDescriptor )
541 return STATUS_INVALID_SECURITY_DESCR;
542 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
543 return STATUS_UNKNOWN_REVISION;
545 return STATUS_SUCCESS;
548 /**************************************************************************
549 * RtlLengthSecurityDescriptor [NTDLL.@]
551 ULONG WINAPI RtlLengthSecurityDescriptor(
552 PSECURITY_DESCRIPTOR pSecurityDescriptor)
554 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
555 ULONG_PTR offset = 0;
556 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
558 if ( lpsd == NULL )
559 return 0;
561 if ( lpsd->Control & SE_SELF_RELATIVE)
562 offset = (ULONG_PTR) lpsd;
564 if ( lpsd->Owner != NULL )
565 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
567 if ( lpsd->Group != NULL )
568 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
570 if ( (lpsd->Control & SE_SACL_PRESENT) &&
571 lpsd->Sacl != NULL )
572 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
574 if ( (lpsd->Control & SE_DACL_PRESENT) &&
575 lpsd->Dacl != NULL )
576 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
578 return Size;
581 /******************************************************************************
582 * RtlGetDaclSecurityDescriptor [NTDLL.@]
585 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
586 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
587 OUT PBOOLEAN lpbDaclPresent,
588 OUT PACL *pDacl,
589 OUT PBOOLEAN lpbDaclDefaulted)
591 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
593 TRACE("(%p,%p,%p,%p)\n",
594 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
596 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
597 return STATUS_UNKNOWN_REVISION ;
599 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
601 if ( SE_SELF_RELATIVE & lpsd->Control)
602 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
603 else
604 *pDacl = lpsd->Dacl;
606 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
609 return STATUS_SUCCESS;
612 /**************************************************************************
613 * RtlSetDaclSecurityDescriptor [NTDLL.@]
615 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
616 PSECURITY_DESCRIPTOR pSecurityDescriptor,
617 BOOLEAN daclpresent,
618 PACL dacl,
619 BOOLEAN dacldefaulted )
621 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
623 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
624 return STATUS_UNKNOWN_REVISION;
625 if (lpsd->Control & SE_SELF_RELATIVE)
626 return STATUS_INVALID_SECURITY_DESCR;
628 if (!daclpresent)
630 lpsd->Control &= ~SE_DACL_PRESENT;
631 return STATUS_SUCCESS;
634 lpsd->Control |= SE_DACL_PRESENT;
635 lpsd->Dacl = dacl;
637 if (dacldefaulted)
638 lpsd->Control |= SE_DACL_DEFAULTED;
639 else
640 lpsd->Control &= ~SE_DACL_DEFAULTED;
642 return STATUS_SUCCESS;
645 /******************************************************************************
646 * RtlGetSaclSecurityDescriptor [NTDLL.@]
649 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
650 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
651 OUT PBOOLEAN lpbSaclPresent,
652 OUT PACL *pSacl,
653 OUT PBOOLEAN lpbSaclDefaulted)
655 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
657 TRACE("(%p,%p,%p,%p)\n",
658 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
660 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
661 return STATUS_UNKNOWN_REVISION;
663 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
665 if (SE_SELF_RELATIVE & lpsd->Control)
666 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
667 else
668 *pSacl = lpsd->Sacl;
670 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
673 return STATUS_SUCCESS;
676 /**************************************************************************
677 * RtlSetSaclSecurityDescriptor [NTDLL.@]
679 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
680 PSECURITY_DESCRIPTOR pSecurityDescriptor,
681 BOOLEAN saclpresent,
682 PACL sacl,
683 BOOLEAN sacldefaulted)
685 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
687 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
688 return STATUS_UNKNOWN_REVISION;
689 if (lpsd->Control & SE_SELF_RELATIVE)
690 return STATUS_INVALID_SECURITY_DESCR;
691 if (!saclpresent) {
692 lpsd->Control &= ~SE_SACL_PRESENT;
693 return 0;
695 lpsd->Control |= SE_SACL_PRESENT;
696 lpsd->Sacl = sacl;
697 if (sacldefaulted)
698 lpsd->Control |= SE_SACL_DEFAULTED;
699 else
700 lpsd->Control &= ~SE_SACL_DEFAULTED;
701 return STATUS_SUCCESS;
704 /**************************************************************************
705 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
707 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
708 PSECURITY_DESCRIPTOR pSecurityDescriptor,
709 PSID *Owner,
710 PBOOLEAN OwnerDefaulted)
712 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
714 if ( !lpsd || !Owner || !OwnerDefaulted )
715 return STATUS_INVALID_PARAMETER;
717 if ( lpsd->Control & SE_OWNER_DEFAULTED )
718 *OwnerDefaulted = TRUE;
719 else
720 *OwnerDefaulted = FALSE;
722 if (lpsd->Owner != NULL)
724 if (lpsd->Control & SE_SELF_RELATIVE)
725 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
726 else
727 *Owner = lpsd->Owner;
730 else
731 *Owner = NULL;
733 return STATUS_SUCCESS;
736 /**************************************************************************
737 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
739 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
740 PSECURITY_DESCRIPTOR pSecurityDescriptor,
741 PSID owner,
742 BOOLEAN ownerdefaulted)
744 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
746 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
747 return STATUS_UNKNOWN_REVISION;
748 if (lpsd->Control & SE_SELF_RELATIVE)
749 return STATUS_INVALID_SECURITY_DESCR;
751 lpsd->Owner = owner;
752 if (ownerdefaulted)
753 lpsd->Control |= SE_OWNER_DEFAULTED;
754 else
755 lpsd->Control &= ~SE_OWNER_DEFAULTED;
756 return STATUS_SUCCESS;
759 /**************************************************************************
760 * RtlSetGroupSecurityDescriptor [NTDLL.@]
762 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
763 PSECURITY_DESCRIPTOR pSecurityDescriptor,
764 PSID group,
765 BOOLEAN groupdefaulted)
767 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
769 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
770 return STATUS_UNKNOWN_REVISION;
771 if (lpsd->Control & SE_SELF_RELATIVE)
772 return STATUS_INVALID_SECURITY_DESCR;
774 lpsd->Group = group;
775 if (groupdefaulted)
776 lpsd->Control |= SE_GROUP_DEFAULTED;
777 else
778 lpsd->Control &= ~SE_GROUP_DEFAULTED;
779 return STATUS_SUCCESS;
782 /**************************************************************************
783 * RtlGetGroupSecurityDescriptor [NTDLL.@]
785 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
786 PSECURITY_DESCRIPTOR pSecurityDescriptor,
787 PSID *Group,
788 PBOOLEAN GroupDefaulted)
790 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
792 if ( !lpsd || !Group || !GroupDefaulted )
793 return STATUS_INVALID_PARAMETER;
795 if ( lpsd->Control & SE_GROUP_DEFAULTED )
796 *GroupDefaulted = TRUE;
797 else
798 *GroupDefaulted = FALSE;
800 if (lpsd->Group != NULL)
802 if (lpsd->Control & SE_SELF_RELATIVE)
803 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
804 else
805 *Group = lpsd->Group;
807 else
808 *Group = NULL;
810 return STATUS_SUCCESS;
813 /**************************************************************************
814 * RtlMakeSelfRelativeSD [NTDLL.@]
816 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
817 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
818 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
819 IN OUT LPDWORD lpdwBufferLength)
821 ULONG_PTR offsetRel;
822 ULONG length;
823 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
824 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
826 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
827 lpdwBufferLength ? *lpdwBufferLength: -1);
829 if (!lpdwBufferLength || !pAbs)
830 return STATUS_INVALID_PARAMETER;
832 length = RtlLengthSecurityDescriptor(pAbs);
833 if (*lpdwBufferLength < length)
835 *lpdwBufferLength = length;
836 return STATUS_BUFFER_TOO_SMALL;
839 if (!pRel)
840 return STATUS_INVALID_PARAMETER;
842 if (pAbs->Control & SE_SELF_RELATIVE)
844 memcpy(pRel, pAbs, length);
845 return STATUS_SUCCESS;
848 pRel->Revision = pAbs->Revision;
849 pRel->Sbz1 = pAbs->Sbz1;
850 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
852 offsetRel = sizeof(SECURITY_DESCRIPTOR);
853 if (pAbs->Owner)
855 pRel->Owner = (PSID) offsetRel;
856 length = RtlLengthSid(pAbs->Owner);
857 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
858 offsetRel += length;
860 else
862 pRel->Owner = NULL;
865 if (pAbs->Group)
867 pRel->Group = (PSID) offsetRel;
868 length = RtlLengthSid(pAbs->Group);
869 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
870 offsetRel += length;
872 else
874 pRel->Group = NULL;
877 if (pAbs->Sacl)
879 pRel->Sacl = (PACL) offsetRel;
880 length = pAbs->Sacl->AclSize;
881 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
882 offsetRel += length;
884 else
886 pRel->Sacl = NULL;
889 if (pAbs->Dacl)
891 pRel->Dacl = (PACL) offsetRel;
892 length = pAbs->Dacl->AclSize;
893 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
895 else
897 pRel->Dacl = NULL;
900 return STATUS_SUCCESS;
904 /**************************************************************************
905 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
907 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
908 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
909 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
910 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
911 OUT PACL pDacl,
912 OUT LPDWORD lpdwDaclSize,
913 OUT PACL pSacl,
914 OUT LPDWORD lpdwSaclSize,
915 OUT PSID pOwner,
916 OUT LPDWORD lpdwOwnerSize,
917 OUT PSID pPrimaryGroup,
918 OUT LPDWORD lpdwPrimaryGroupSize)
920 NTSTATUS status = STATUS_SUCCESS;
921 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
922 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
924 if (!pRel ||
925 !lpdwAbsoluteSecurityDescriptorSize ||
926 !lpdwDaclSize ||
927 !lpdwSaclSize ||
928 !lpdwOwnerSize ||
929 !lpdwPrimaryGroupSize ||
930 ~pRel->Control & SE_SELF_RELATIVE)
931 return STATUS_INVALID_PARAMETER;
933 /* Confirm buffers are sufficiently large */
934 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
936 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
937 status = STATUS_BUFFER_TOO_SMALL;
940 if (pRel->Control & SE_DACL_PRESENT &&
941 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
943 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
944 status = STATUS_BUFFER_TOO_SMALL;
947 if (pRel->Control & SE_SACL_PRESENT &&
948 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
950 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
951 status = STATUS_BUFFER_TOO_SMALL;
954 if (pRel->Owner &&
955 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
957 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (pRel->Group &&
962 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
964 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
965 status = STATUS_BUFFER_TOO_SMALL;
968 if (status != STATUS_SUCCESS)
969 return status;
971 /* Copy structures, and clear the ones we don't set */
972 pAbs->Revision = pRel->Revision;
973 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
974 pAbs->Sacl = NULL;
975 pAbs->Dacl = NULL;
976 pAbs->Owner = NULL;
977 pAbs->Group = NULL;
979 if (pRel->Control & SE_SACL_PRESENT)
981 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
983 memcpy(pSacl, pAcl, pAcl->AclSize);
984 pAbs->Sacl = pSacl;
987 if (pRel->Control & SE_DACL_PRESENT)
989 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
990 memcpy(pDacl, pAcl, pAcl->AclSize);
991 pAbs->Dacl = pDacl;
994 if (pRel->Owner)
996 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
997 memcpy(pOwner, psid, RtlLengthSid(psid));
998 pAbs->Owner = pOwner;
1001 if (pRel->Group)
1003 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1004 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1005 pAbs->Group = pPrimaryGroup;
1008 return status;
1011 /******************************************************************************
1012 * RtlGetControlSecurityDescriptor (NTDLL.@)
1014 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1015 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1016 PSECURITY_DESCRIPTOR_CONTROL pControl,
1017 LPDWORD lpdwRevision)
1019 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1021 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1023 *lpdwRevision = lpsd->Revision;
1025 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1026 return STATUS_UNKNOWN_REVISION;
1028 *pControl = lpsd->Control;
1030 return STATUS_SUCCESS;
1034 /**************************************************************************
1035 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1037 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1038 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1039 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1040 PULONG BufferLength)
1042 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1044 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1045 SelfRelativeSecurityDescriptor, BufferLength);
1047 if (abs->Control & SE_SELF_RELATIVE)
1048 return STATUS_BAD_DESCRIPTOR_FORMAT;
1050 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1051 SelfRelativeSecurityDescriptor, BufferLength);
1056 * access control list's
1059 /**************************************************************************
1060 * RtlCreateAcl [NTDLL.@]
1062 * NOTES
1063 * This should return NTSTATUS
1065 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1067 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1069 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1070 return STATUS_INVALID_PARAMETER;
1071 if (size<sizeof(ACL))
1072 return STATUS_BUFFER_TOO_SMALL;
1073 if (size>0xFFFF)
1074 return STATUS_INVALID_PARAMETER;
1076 memset(acl,'\0',sizeof(ACL));
1077 acl->AclRevision = rev;
1078 acl->AclSize = size;
1079 acl->AceCount = 0;
1080 return STATUS_SUCCESS;
1083 /**************************************************************************
1084 * RtlFirstFreeAce [NTDLL.@]
1085 * looks for the AceCount+1 ACE, and if it is still within the alloced
1086 * ACL, return a pointer to it
1088 BOOLEAN WINAPI RtlFirstFreeAce(
1089 PACL acl,
1090 PACE_HEADER *x)
1092 PACE_HEADER ace;
1093 int i;
1095 *x = 0;
1096 ace = (PACE_HEADER)(acl+1);
1097 for (i=0;i<acl->AceCount;i++) {
1098 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1099 return 0;
1100 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1102 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1103 return 0;
1104 *x = ace;
1105 return 1;
1108 /**************************************************************************
1109 * RtlAddAce [NTDLL.@]
1111 NTSTATUS WINAPI RtlAddAce(
1112 PACL acl,
1113 DWORD rev,
1114 DWORD xnrofaces,
1115 PACE_HEADER acestart,
1116 DWORD acelen)
1118 PACE_HEADER ace,targetace;
1119 int nrofaces;
1121 if (acl->AclRevision != ACL_REVISION)
1122 return STATUS_INVALID_PARAMETER;
1123 if (!RtlFirstFreeAce(acl,&targetace))
1124 return STATUS_INVALID_PARAMETER;
1125 nrofaces=0;ace=acestart;
1126 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1127 nrofaces++;
1128 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1130 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1131 return STATUS_INVALID_PARAMETER;
1132 memcpy((LPBYTE)targetace,acestart,acelen);
1133 acl->AceCount+=nrofaces;
1134 return STATUS_SUCCESS;
1137 /**************************************************************************
1138 * RtlDeleteAce [NTDLL.@]
1140 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1142 NTSTATUS status;
1143 PACE_HEADER pAce;
1145 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1147 if (STATUS_SUCCESS == status)
1149 PACE_HEADER pcAce;
1150 DWORD len = 0;
1152 /* skip over the ACE we are deleting */
1153 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1154 dwAceIndex++;
1156 /* calculate the length of the rest */
1157 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1159 len += pcAce->AceSize;
1160 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1163 /* slide them all backwards */
1164 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1165 pAcl->AceCount--;
1168 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1170 return status;
1173 /******************************************************************************
1174 * RtlAddAccessAllowedAce [NTDLL.@]
1176 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1177 IN OUT PACL pAcl,
1178 IN DWORD dwAceRevision,
1179 IN DWORD AccessMask,
1180 IN PSID pSid)
1182 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1185 /******************************************************************************
1186 * RtlAddAccessAllowedAceEx [NTDLL.@]
1188 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1189 IN OUT PACL pAcl,
1190 IN DWORD dwAceRevision,
1191 IN DWORD AceFlags,
1192 IN DWORD AccessMask,
1193 IN PSID pSid)
1195 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1197 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1198 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1201 /******************************************************************************
1202 * RtlAddAccessDeniedAce [NTDLL.@]
1204 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1205 IN OUT PACL pAcl,
1206 IN DWORD dwAceRevision,
1207 IN DWORD AccessMask,
1208 IN PSID pSid)
1210 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1213 /******************************************************************************
1214 * RtlAddAccessDeniedAceEx [NTDLL.@]
1216 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1217 IN OUT PACL pAcl,
1218 IN DWORD dwAceRevision,
1219 IN DWORD AceFlags,
1220 IN DWORD AccessMask,
1221 IN PSID pSid)
1223 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1225 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1226 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1229 /**************************************************************************
1230 * RtlAddAuditAccessAce [NTDLL.@]
1232 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1233 IN OUT PACL pAcl,
1234 IN DWORD dwAceRevision,
1235 IN DWORD dwAceFlags,
1236 IN DWORD dwAccessMask,
1237 IN PSID pSid,
1238 IN BOOL bAuditSuccess,
1239 IN BOOL bAuditFailure)
1241 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1242 pSid,bAuditSuccess,bAuditFailure);
1244 if (bAuditSuccess)
1245 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1247 if (bAuditFailure)
1248 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1250 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1251 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1254 /**************************************************************************
1255 * RtlAddAuditAccessAce [NTDLL.@]
1257 NTSTATUS WINAPI RtlAddAuditAccessAce(
1258 IN OUT PACL pAcl,
1259 IN DWORD dwAceRevision,
1260 IN DWORD dwAccessMask,
1261 IN PSID pSid,
1262 IN BOOL bAuditSuccess,
1263 IN BOOL bAuditFailure)
1265 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1268 /******************************************************************************
1269 * RtlValidAcl [NTDLL.@]
1271 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1273 BOOLEAN ret;
1274 TRACE("(%p)\n", pAcl);
1276 __TRY
1278 PACE_HEADER ace;
1279 int i;
1281 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1282 pAcl->AclRevision > MAX_ACL_REVISION)
1283 ret = FALSE;
1284 else
1286 ace = (PACE_HEADER)(pAcl+1);
1287 ret = TRUE;
1288 for (i=0;i<=pAcl->AceCount;i++)
1290 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1292 ret = FALSE;
1293 break;
1295 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1299 __EXCEPT_PAGE_FAULT
1301 WARN("(%p): invalid pointer!\n", pAcl);
1302 return 0;
1304 __ENDTRY
1305 return ret;
1308 /******************************************************************************
1309 * RtlGetAce [NTDLL.@]
1311 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1313 PACE_HEADER ace;
1315 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1317 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1318 return STATUS_INVALID_PARAMETER;
1320 ace = (PACE_HEADER)(pAcl + 1);
1321 for (;dwAceIndex;dwAceIndex--)
1322 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1324 *pAce = (LPVOID) ace;
1326 return STATUS_SUCCESS;
1330 * misc
1333 /******************************************************************************
1334 * RtlAdjustPrivilege [NTDLL.@]
1336 * Enables or disables a privilege from the calling thread or process.
1338 * PARAMS
1339 * Privilege [I] Privilege index to change.
1340 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1341 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1342 * Enabled [O] Whether privilege was previously enabled or disabled.
1344 * RETURNS
1345 * Success: STATUS_SUCCESS.
1346 * Failure: NTSTATUS code.
1348 * SEE ALSO
1349 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1352 NTSTATUS WINAPI
1353 RtlAdjustPrivilege(ULONG Privilege,
1354 BOOLEAN Enable,
1355 BOOLEAN CurrentThread,
1356 PBOOLEAN Enabled)
1358 TOKEN_PRIVILEGES NewState;
1359 TOKEN_PRIVILEGES OldState;
1360 ULONG ReturnLength;
1361 HANDLE TokenHandle;
1362 NTSTATUS Status;
1364 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1365 CurrentThread ? "TRUE" : "FALSE", Enabled);
1367 if (CurrentThread)
1369 Status = NtOpenThreadToken(GetCurrentThread(),
1370 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1371 FALSE,
1372 &TokenHandle);
1374 else
1376 Status = NtOpenProcessToken(GetCurrentProcess(),
1377 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1378 &TokenHandle);
1381 if (!NT_SUCCESS(Status))
1383 WARN("Retrieving token handle failed (Status %x)\n", Status);
1384 return Status;
1387 OldState.PrivilegeCount = 1;
1389 NewState.PrivilegeCount = 1;
1390 NewState.Privileges[0].Luid.LowPart = Privilege;
1391 NewState.Privileges[0].Luid.HighPart = 0;
1392 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1394 Status = NtAdjustPrivilegesToken(TokenHandle,
1395 FALSE,
1396 &NewState,
1397 sizeof(TOKEN_PRIVILEGES),
1398 &OldState,
1399 &ReturnLength);
1400 NtClose (TokenHandle);
1401 if (Status == STATUS_NOT_ALL_ASSIGNED)
1403 TRACE("Failed to assign all privileges\n");
1404 return STATUS_PRIVILEGE_NOT_HELD;
1406 if (!NT_SUCCESS(Status))
1408 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1409 return Status;
1412 if (OldState.PrivilegeCount == 0)
1413 *Enabled = Enable;
1414 else
1415 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1417 return STATUS_SUCCESS;
1420 /******************************************************************************
1421 * RtlImpersonateSelf [NTDLL.@]
1423 * Makes an impersonation token that represents the process user and assigns
1424 * to the current thread.
1426 * PARAMS
1427 * ImpersonationLevel [I] Level at which to impersonate.
1429 * RETURNS
1430 * Success: STATUS_SUCCESS.
1431 * Failure: NTSTATUS code.
1433 NTSTATUS WINAPI
1434 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1436 NTSTATUS Status;
1437 OBJECT_ATTRIBUTES ObjectAttributes;
1438 HANDLE ProcessToken;
1439 HANDLE ImpersonationToken;
1441 TRACE("(%08x)\n", ImpersonationLevel);
1443 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1444 &ProcessToken);
1445 if (Status != STATUS_SUCCESS)
1446 return Status;
1448 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1450 Status = NtDuplicateToken( ProcessToken,
1451 TOKEN_IMPERSONATE,
1452 &ObjectAttributes,
1453 ImpersonationLevel,
1454 TokenImpersonation,
1455 &ImpersonationToken );
1456 if (Status != STATUS_SUCCESS)
1458 NtClose( ProcessToken );
1459 return Status;
1462 Status = NtSetInformationThread( GetCurrentThread(),
1463 ThreadImpersonationToken,
1464 &ImpersonationToken,
1465 sizeof(ImpersonationToken) );
1467 NtClose( ImpersonationToken );
1468 NtClose( ProcessToken );
1470 return Status;
1473 /******************************************************************************
1474 * NtAccessCheck [NTDLL.@]
1475 * ZwAccessCheck [NTDLL.@]
1477 * Checks that a user represented by a token is allowed to access an object
1478 * represented by a security descriptor.
1480 * PARAMS
1481 * SecurityDescriptor [I] The security descriptor of the object to check.
1482 * ClientToken [I] Token of the user accessing the object.
1483 * DesiredAccess [I] The desired access to the object.
1484 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1485 * PrivilegeSet [I/O] Privileges used during the access check.
1486 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1487 * GrantedAccess [O] The actual access rights granted.
1488 * AccessStatus [O] The status of the access check.
1490 * RETURNS
1491 * NTSTATUS code.
1493 * NOTES
1494 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1495 * the maximum access rights allowed by the SD and returns them in
1496 * GrantedAccess.
1497 * The SecurityDescriptor must have a valid owner and groups present,
1498 * otherwise the function will fail.
1500 NTSTATUS WINAPI
1501 NtAccessCheck(
1502 PSECURITY_DESCRIPTOR SecurityDescriptor,
1503 HANDLE ClientToken,
1504 ACCESS_MASK DesiredAccess,
1505 PGENERIC_MAPPING GenericMapping,
1506 PPRIVILEGE_SET PrivilegeSet,
1507 PULONG ReturnLength,
1508 PULONG GrantedAccess,
1509 NTSTATUS *AccessStatus)
1511 NTSTATUS status;
1513 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1514 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1515 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1517 SERVER_START_REQ( access_check )
1519 struct security_descriptor sd;
1520 PSID owner;
1521 PSID group;
1522 PACL sacl;
1523 PACL dacl;
1524 BOOLEAN defaulted, present;
1525 DWORD revision;
1526 SECURITY_DESCRIPTOR_CONTROL control;
1528 req->handle = ClientToken;
1529 req->desired_access = DesiredAccess;
1530 req->mapping_read = GenericMapping->GenericRead;
1531 req->mapping_write = GenericMapping->GenericWrite;
1532 req->mapping_execute = GenericMapping->GenericExecute;
1533 req->mapping_all = GenericMapping->GenericAll;
1535 /* marshal security descriptor */
1536 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1537 sd.control = control & ~SE_SELF_RELATIVE;
1538 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1539 sd.owner_len = RtlLengthSid( owner );
1540 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1541 sd.group_len = RtlLengthSid( group );
1542 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1543 sd.sacl_len = ((present && sacl) ? sacl->AclSize : 0);
1544 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1545 sd.dacl_len = ((present && dacl) ? dacl->AclSize : 0);
1547 wine_server_add_data( req, &sd, sizeof(sd) );
1548 wine_server_add_data( req, owner, sd.owner_len );
1549 wine_server_add_data( req, group, sd.group_len );
1550 wine_server_add_data( req, sacl, sd.sacl_len );
1551 wine_server_add_data( req, dacl, sd.dacl_len );
1553 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1555 status = wine_server_call( req );
1557 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1558 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1560 if (status == STATUS_SUCCESS)
1562 *AccessStatus = reply->access_status;
1563 *GrantedAccess = reply->access_granted;
1566 SERVER_END_REQ;
1568 return status;
1571 /******************************************************************************
1572 * NtSetSecurityObject [NTDLL.@]
1573 * ZwSetSecurityObject [NTDLL.@]
1575 * Sets specified parts of the object's security descriptor.
1577 * PARAMS
1578 * Handle [I] Handle to the object to change security descriptor of.
1579 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1580 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1582 * RETURNS
1583 * NTSTATUS code.
1586 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1587 SECURITY_INFORMATION SecurityInformation,
1588 PSECURITY_DESCRIPTOR SecurityDescriptor)
1590 NTSTATUS status;
1591 struct security_descriptor sd;
1592 PACL dacl = NULL, sacl = NULL;
1593 PSID owner = NULL, group = NULL;
1594 BOOLEAN defaulted, present;
1595 DWORD revision;
1596 SECURITY_DESCRIPTOR_CONTROL control;
1598 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1600 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1602 memset( &sd, 0, sizeof(sd) );
1603 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1604 if (status != STATUS_SUCCESS) return status;
1605 sd.control = control & ~SE_SELF_RELATIVE;
1607 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1609 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1610 if (status != STATUS_SUCCESS) return status;
1611 if (!(sd.owner_len = RtlLengthSid( owner )))
1612 return STATUS_INVALID_SECURITY_DESCR;
1615 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1617 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1618 if (status != STATUS_SUCCESS) return status;
1619 if (!(sd.group_len = RtlLengthSid( group )))
1620 return STATUS_INVALID_SECURITY_DESCR;
1623 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1625 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1626 if (status != STATUS_SUCCESS) return status;
1627 sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1628 sd.control |= SE_SACL_PRESENT;
1631 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1633 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1634 if (status != STATUS_SUCCESS) return status;
1635 sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1636 sd.control |= SE_DACL_PRESENT;
1639 SERVER_START_REQ( set_security_object )
1641 req->handle = Handle;
1642 req->security_info = SecurityInformation;
1644 wine_server_add_data( req, &sd, sizeof(sd) );
1645 wine_server_add_data( req, owner, sd.owner_len );
1646 wine_server_add_data( req, group, sd.group_len );
1647 wine_server_add_data( req, sacl, sd.sacl_len );
1648 wine_server_add_data( req, dacl, sd.dacl_len );
1649 status = wine_server_call( req );
1651 SERVER_END_REQ;
1653 return status;
1656 /******************************************************************************
1657 * RtlConvertSidToUnicodeString (NTDLL.@)
1659 * The returned SID is used to access the USER registry hive usually
1661 * the native function returns something like
1662 * "S-1-5-21-0000000000-000000000-0000000000-500";
1664 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1665 PUNICODE_STRING String,
1666 PSID pSid,
1667 BOOLEAN AllocateString)
1669 static const WCHAR formatW[] = {'-','%','u',0};
1670 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1671 WCHAR *p = buffer;
1672 const SID *sid = (const SID *)pSid;
1673 DWORD i, len;
1675 *p++ = 'S';
1676 p += sprintfW( p, formatW, sid->Revision );
1677 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1678 sid->IdentifierAuthority.Value[4] ),
1679 MAKEWORD( sid->IdentifierAuthority.Value[3],
1680 sid->IdentifierAuthority.Value[2] )));
1681 for (i = 0; i < sid->SubAuthorityCount; i++)
1682 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1684 len = (p + 1 - buffer) * sizeof(WCHAR);
1686 String->Length = len - sizeof(WCHAR);
1687 if (AllocateString)
1689 String->MaximumLength = len;
1690 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1691 return STATUS_NO_MEMORY;
1693 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1695 memcpy( String->Buffer, buffer, len );
1696 return STATUS_SUCCESS;
1699 /******************************************************************************
1700 * RtlQueryInformationAcl (NTDLL.@)
1702 NTSTATUS WINAPI RtlQueryInformationAcl(
1703 PACL pAcl,
1704 LPVOID pAclInformation,
1705 DWORD nAclInformationLength,
1706 ACL_INFORMATION_CLASS dwAclInformationClass)
1708 NTSTATUS status = STATUS_SUCCESS;
1710 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1711 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1713 switch (dwAclInformationClass)
1715 case AclRevisionInformation:
1717 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1719 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1720 status = STATUS_INVALID_PARAMETER;
1721 else
1722 paclrev->AclRevision = pAcl->AclRevision;
1724 break;
1727 case AclSizeInformation:
1729 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1731 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1732 status = STATUS_INVALID_PARAMETER;
1733 else
1735 INT i;
1736 PACE_HEADER ace;
1738 paclsize->AceCount = pAcl->AceCount;
1740 paclsize->AclBytesInUse = 0;
1741 ace = (PACE_HEADER) (pAcl + 1);
1743 for (i = 0; i < pAcl->AceCount; i++)
1745 paclsize->AclBytesInUse += ace->AceSize;
1746 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1749 if (pAcl->AclSize < paclsize->AclBytesInUse)
1751 WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1752 paclsize->AclBytesFree = 0;
1753 paclsize->AclBytesInUse = pAcl->AclSize;
1755 else
1756 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1759 break;
1762 default:
1763 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1764 status = STATUS_INVALID_PARAMETER;
1767 return status;