ntdll: More error checking. Properly handle NULL ACLs.
[wine.git] / dlls / ntdll / sec.c
blob64384cf1b450b628c06837a502aa4e41a702bb04
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 "excpt.h"
41 #include "wine/library.h"
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
47 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
49 /* helper function to copy an ACL */
50 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
52 DWORD size;
54 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
55 return FALSE;
57 size = ((ACL *)pSourceAcl)->AclSize;
58 if (nDestinationAclLength < size)
59 return FALSE;
61 memmove(pDestinationAcl, pSourceAcl, size);
62 return TRUE;
65 /* generically adds an ACE to an ACL */
66 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
67 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
69 ACE_HEADER *pAceHeader;
70 DWORD dwLengthSid;
71 DWORD dwAceSize;
72 DWORD *pAccessMask;
73 DWORD *pSidStart;
75 if (!RtlValidSid(pSid))
76 return STATUS_INVALID_SID;
78 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
79 return STATUS_REVISION_MISMATCH;
81 if (!RtlValidAcl(pAcl))
82 return STATUS_INVALID_ACL;
84 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
85 return STATUS_INVALID_ACL;
87 if (!pAceHeader)
88 return STATUS_ALLOTTED_SPACE_EXCEEDED;
90 /* calculate generic size of the ACE */
91 dwLengthSid = RtlLengthSid(pSid);
92 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
93 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
94 return STATUS_ALLOTTED_SPACE_EXCEEDED;
96 /* fill the new ACE */
97 pAceHeader->AceType = dwAceType;
98 pAceHeader->AceFlags = dwAceFlags;
99 pAceHeader->AceSize = dwAceSize;
101 /* skip past the ACE_HEADER of the ACE */
102 pAccessMask = (DWORD *)(pAceHeader + 1);
103 *pAccessMask = dwAccessMask;
105 /* skip past ACE->Mask */
106 pSidStart = pAccessMask + 1;
107 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
109 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
110 pAcl->AceCount++;
112 return STATUS_SUCCESS;
116 * SID FUNCTIONS
119 /******************************************************************************
120 * RtlAllocateAndInitializeSid [NTDLL.@]
123 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
124 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
125 BYTE nSubAuthorityCount,
126 DWORD nSubAuthority0, DWORD nSubAuthority1,
127 DWORD nSubAuthority2, DWORD nSubAuthority3,
128 DWORD nSubAuthority4, DWORD nSubAuthority5,
129 DWORD nSubAuthority6, DWORD nSubAuthority7,
130 PSID *pSid )
132 SID *tmp_sid;
134 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
135 pIdentifierAuthority,nSubAuthorityCount,
136 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
137 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
139 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
141 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
142 RtlLengthRequiredSid(nSubAuthorityCount))))
143 return STATUS_NO_MEMORY;
145 tmp_sid->Revision = SID_REVISION;
147 if (pIdentifierAuthority)
148 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
149 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
151 switch( nSubAuthorityCount )
153 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
154 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
155 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
156 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
157 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
158 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
159 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
160 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
161 break;
163 *pSid = tmp_sid;
164 return STATUS_SUCCESS;
167 /******************************************************************************
168 * RtlEqualSid [NTDLL.@]
170 * Determine if two SIDs are equal.
172 * PARAMS
173 * pSid1 [I] Source SID
174 * pSid2 [I] SID to compare with
176 * RETURNS
177 * TRUE, if pSid1 is equal to pSid2,
178 * FALSE otherwise.
180 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
182 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
183 return FALSE;
185 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
186 return FALSE;
188 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
189 return FALSE;
191 return TRUE;
194 /******************************************************************************
195 * RtlEqualPrefixSid [NTDLL.@]
197 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
199 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
200 return FALSE;
202 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
203 return FALSE;
205 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
206 return FALSE;
208 return TRUE;
212 /******************************************************************************
213 * RtlFreeSid [NTDLL.@]
215 * Free the resources used by a SID.
217 * PARAMS
218 * pSid [I] SID to Free.
220 * RETURNS
221 * STATUS_SUCCESS.
223 DWORD WINAPI RtlFreeSid(PSID pSid)
225 TRACE("(%p)\n", pSid);
226 RtlFreeHeap( GetProcessHeap(), 0, pSid );
227 return STATUS_SUCCESS;
230 /**************************************************************************
231 * RtlLengthRequiredSid [NTDLL.@]
233 * Determine the amount of memory a SID will use
235 * PARAMS
236 * nrofsubauths [I] Number of Sub Authorities in the SID.
238 * RETURNS
239 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
241 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
243 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
246 /**************************************************************************
247 * RtlLengthSid [NTDLL.@]
249 * Determine the amount of memory a SID is using
251 * PARAMS
252 * pSid [I] SID to get the size of.
254 * RETURNS
255 * The size, in bytes, of pSid.
257 DWORD WINAPI RtlLengthSid(PSID pSid)
259 TRACE("sid=%p\n",pSid);
260 if (!pSid) return 0;
261 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
264 /**************************************************************************
265 * RtlInitializeSid [NTDLL.@]
267 * Initialise a SID.
269 * PARAMS
270 * pSid [I] SID to initialise
271 * pIdentifierAuthority [I] Identifier Authority
272 * nSubAuthorityCount [I] Number of Sub Authorities
274 * RETURNS
275 * Success: TRUE. pSid is initialised with the details given.
276 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
278 BOOL WINAPI RtlInitializeSid(
279 PSID pSid,
280 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
281 BYTE nSubAuthorityCount)
283 int i;
284 SID* pisid=pSid;
286 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
287 return FALSE;
289 pisid->Revision = SID_REVISION;
290 pisid->SubAuthorityCount = nSubAuthorityCount;
291 if (pIdentifierAuthority)
292 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
294 for (i = 0; i < nSubAuthorityCount; i++)
295 *RtlSubAuthoritySid(pSid, i) = 0;
297 return TRUE;
300 /**************************************************************************
301 * RtlSubAuthoritySid [NTDLL.@]
303 * Return the Sub Authority of a SID
305 * PARAMS
306 * pSid [I] SID to get the Sub Authority from.
307 * nSubAuthority [I] Sub Authority number.
309 * RETURNS
310 * A pointer to The Sub Authority value of pSid.
312 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
314 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
317 /**************************************************************************
318 * RtlIdentifierAuthoritySid [NTDLL.@]
320 * Return the Identifier Authority of a SID.
322 * PARAMS
323 * pSid [I] SID to get the Identifier Authority from.
325 * RETURNS
326 * A pointer to the Identifier Authority value of pSid.
328 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
330 return &(((SID*)pSid)->IdentifierAuthority);
333 /**************************************************************************
334 * RtlSubAuthorityCountSid [NTDLL.@]
336 * Get the number of Sub Authorities in a SID.
338 * PARAMS
339 * pSid [I] SID to get the count from.
341 * RETURNS
342 * A pointer to the Sub Authority count of pSid.
344 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
346 return &(((SID*)pSid)->SubAuthorityCount);
349 /**************************************************************************
350 * RtlCopySid [NTDLL.@]
352 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
354 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
355 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
356 return FALSE;
358 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
359 return FALSE;
361 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
362 return TRUE;
364 /******************************************************************************
365 * RtlValidSid [NTDLL.@]
367 * Determine if a SID is valid.
369 * PARAMS
370 * pSid [I] SID to check
372 * RETURNS
373 * TRUE if pSid is valid,
374 * FALSE otherwise.
376 BOOLEAN WINAPI RtlValidSid( PSID pSid )
378 BOOL ret;
379 __TRY
381 ret = TRUE;
382 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
383 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
385 ret = FALSE;
388 __EXCEPT_PAGE_FAULT
390 WARN("(%p): invalid pointer!\n", pSid);
391 return FALSE;
393 __ENDTRY
394 return ret;
399 * security descriptor functions
402 /**************************************************************************
403 * RtlCreateSecurityDescriptor [NTDLL.@]
405 * Initialise a SECURITY_DESCRIPTOR.
407 * PARAMS
408 * lpsd [O] Descriptor to initialise.
409 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
411 * RETURNS
412 * Success: STATUS_SUCCESS.
413 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
415 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
416 PSECURITY_DESCRIPTOR lpsd,
417 DWORD rev)
419 if (rev!=SECURITY_DESCRIPTOR_REVISION)
420 return STATUS_UNKNOWN_REVISION;
421 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
422 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
423 return STATUS_SUCCESS;
426 /**************************************************************************
427 * RtlCopySecurityDescriptor [NTDLL.@]
429 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
431 * PARAMS
432 * pSourceSD [O] SD to copy from.
433 * pDestinationSD [I] Destination SD.
435 * RETURNS
436 * Success: STATUS_SUCCESS.
437 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
439 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
441 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
442 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
443 PSID Owner, Group;
444 PACL Dacl, Sacl;
445 BOOLEAN defaulted, present;
446 DWORD length;
447 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
449 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
450 return STATUS_UNKNOWN_REVISION;
452 /* copy initial data */
453 destSD->Revision = srcSD->Revision;
454 destSD->Sbz1 = srcSD->Sbz1;
455 destSD->Control = srcSD->Control;
457 /* copy Owner */
458 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
459 length = RtlLengthSid(Owner);
461 if (isSelfRelative)
463 destSD->Owner = srcSD->Owner;
464 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
466 else
468 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
469 RtlCopySid(length, destSD->Owner, Owner);
472 /* copy Group */
473 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
474 length = RtlLengthSid(Group);
476 if (isSelfRelative)
478 destSD->Group = srcSD->Group;
479 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
481 else
483 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
484 RtlCopySid(length, destSD->Group, Group);
487 /* copy Dacl */
488 if (srcSD->Control & SE_DACL_PRESENT)
490 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
491 length = Dacl->AclSize;
493 if (isSelfRelative)
495 destSD->Dacl = srcSD->Dacl;
496 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
498 else
500 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
501 copy_acl(length, destSD->Dacl, Dacl);
505 /* copy Sacl */
506 if (srcSD->Control & SE_SACL_PRESENT)
508 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
509 length = Sacl->AclSize;
511 if (isSelfRelative)
513 destSD->Sacl = srcSD->Sacl;
514 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
516 else
518 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
519 copy_acl(length, destSD->Sacl, Sacl);
523 return STATUS_SUCCESS;
526 /**************************************************************************
527 * RtlValidSecurityDescriptor [NTDLL.@]
529 * Determine if a SECURITY_DESCRIPTOR is valid.
531 * PARAMS
532 * SecurityDescriptor [I] Descriptor to check.
534 * RETURNS
535 * Success: STATUS_SUCCESS.
536 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
538 NTSTATUS WINAPI RtlValidSecurityDescriptor(
539 PSECURITY_DESCRIPTOR SecurityDescriptor)
541 if ( ! SecurityDescriptor )
542 return STATUS_INVALID_SECURITY_DESCR;
543 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
544 return STATUS_UNKNOWN_REVISION;
546 return STATUS_SUCCESS;
549 /**************************************************************************
550 * RtlLengthSecurityDescriptor [NTDLL.@]
552 ULONG WINAPI RtlLengthSecurityDescriptor(
553 PSECURITY_DESCRIPTOR pSecurityDescriptor)
555 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
556 ULONG offset = 0;
557 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
559 if ( lpsd == NULL )
560 return 0;
562 if ( lpsd->Control & SE_SELF_RELATIVE)
563 offset = (ULONG) lpsd;
565 if ( lpsd->Owner != NULL )
566 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
568 if ( lpsd->Group != NULL )
569 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
571 if ( (lpsd->Control & SE_SACL_PRESENT) &&
572 lpsd->Sacl != NULL )
573 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
575 if ( (lpsd->Control & SE_DACL_PRESENT) &&
576 lpsd->Dacl != NULL )
577 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
579 return Size;
582 /******************************************************************************
583 * RtlGetDaclSecurityDescriptor [NTDLL.@]
586 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
587 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
588 OUT PBOOLEAN lpbDaclPresent,
589 OUT PACL *pDacl,
590 OUT PBOOLEAN lpbDaclDefaulted)
592 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
594 TRACE("(%p,%p,%p,%p)\n",
595 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
597 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
598 return STATUS_UNKNOWN_REVISION ;
600 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
602 if ( SE_SELF_RELATIVE & lpsd->Control)
603 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
604 else
605 *pDacl = lpsd->Dacl;
607 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
610 return STATUS_SUCCESS;
613 /**************************************************************************
614 * RtlSetDaclSecurityDescriptor [NTDLL.@]
616 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
617 PSECURITY_DESCRIPTOR pSecurityDescriptor,
618 BOOLEAN daclpresent,
619 PACL dacl,
620 BOOLEAN dacldefaulted )
622 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
624 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
625 return STATUS_UNKNOWN_REVISION;
626 if (lpsd->Control & SE_SELF_RELATIVE)
627 return STATUS_INVALID_SECURITY_DESCR;
629 if (!daclpresent)
630 { lpsd->Control &= ~SE_DACL_PRESENT;
631 return TRUE;
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)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->Owner != NULL)
719 if (lpsd->Control & SE_SELF_RELATIVE)
720 *Owner = (PSID)((LPBYTE)lpsd +
721 (ULONG)lpsd->Owner);
722 else
723 *Owner = lpsd->Owner;
725 if ( lpsd->Control & SE_OWNER_DEFAULTED )
726 *OwnerDefaulted = TRUE;
727 else
728 *OwnerDefaulted = FALSE;
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->Group != NULL)
797 if (lpsd->Control & SE_SELF_RELATIVE)
798 *Group = (PSID)((LPBYTE)lpsd +
799 (ULONG)lpsd->Group);
800 else
801 *Group = lpsd->Group;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
805 else
806 *GroupDefaulted = FALSE;
808 else
809 *Group = NULL;
811 return STATUS_SUCCESS;
814 /**************************************************************************
815 * RtlMakeSelfRelativeSD [NTDLL.@]
817 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
818 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
819 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
820 IN OUT LPDWORD lpdwBufferLength)
822 ULONG offsetRel;
823 ULONG length;
824 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
825 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
827 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
828 lpdwBufferLength ? *lpdwBufferLength: -1);
830 if (!lpdwBufferLength || !pAbs)
831 return STATUS_INVALID_PARAMETER;
833 length = RtlLengthSecurityDescriptor(pAbs);
834 if (*lpdwBufferLength < length)
836 *lpdwBufferLength = length;
837 return STATUS_BUFFER_TOO_SMALL;
840 if (!pRel)
841 return STATUS_INVALID_PARAMETER;
843 if (pAbs->Control & SE_SELF_RELATIVE)
845 memcpy(pRel, pAbs, length);
846 return STATUS_SUCCESS;
849 pRel->Revision = pAbs->Revision;
850 pRel->Sbz1 = pAbs->Sbz1;
851 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
853 offsetRel = sizeof(SECURITY_DESCRIPTOR);
854 pRel->Owner = (PSID) offsetRel;
855 length = RtlLengthSid(pAbs->Owner);
856 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
858 offsetRel += length;
859 pRel->Group = (PSID) offsetRel;
860 length = RtlLengthSid(pAbs->Group);
861 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
863 if (pRel->Control & SE_SACL_PRESENT)
865 offsetRel += length;
866 pRel->Sacl = (PACL) offsetRel;
867 length = pAbs->Sacl->AclSize;
868 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
870 else
872 pRel->Sacl = NULL;
875 if (pRel->Control & SE_DACL_PRESENT)
877 offsetRel += length;
878 pRel->Dacl = (PACL) offsetRel;
879 length = pAbs->Dacl->AclSize;
880 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
882 else
884 pRel->Dacl = NULL;
887 return STATUS_SUCCESS;
891 /**************************************************************************
892 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
894 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
895 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
896 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
897 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
898 OUT PACL pDacl,
899 OUT LPDWORD lpdwDaclSize,
900 OUT PACL pSacl,
901 OUT LPDWORD lpdwSaclSize,
902 OUT PSID pOwner,
903 OUT LPDWORD lpdwOwnerSize,
904 OUT PSID pPrimaryGroup,
905 OUT LPDWORD lpdwPrimaryGroupSize)
907 NTSTATUS status = STATUS_SUCCESS;
908 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
909 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
911 if (!pRel ||
912 !lpdwAbsoluteSecurityDescriptorSize ||
913 !lpdwDaclSize ||
914 !lpdwSaclSize ||
915 !lpdwOwnerSize ||
916 !lpdwPrimaryGroupSize ||
917 ~pRel->Control & SE_SELF_RELATIVE)
918 return STATUS_INVALID_PARAMETER;
920 /* Confirm buffers are sufficiently large */
921 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
923 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
924 status = STATUS_BUFFER_TOO_SMALL;
927 if (pRel->Control & SE_DACL_PRESENT &&
928 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
930 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
931 status = STATUS_BUFFER_TOO_SMALL;
934 if (pRel->Control & SE_SACL_PRESENT &&
935 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
937 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
938 status = STATUS_BUFFER_TOO_SMALL;
941 if (pRel->Owner &&
942 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
944 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
945 status = STATUS_BUFFER_TOO_SMALL;
948 if (pRel->Group &&
949 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
951 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
952 status = STATUS_BUFFER_TOO_SMALL;
955 if (status != STATUS_SUCCESS)
956 return status;
958 /* Copy structures */
959 pAbs->Revision = pRel->Revision;
960 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
962 if (pRel->Control & SE_SACL_PRESENT)
964 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
966 memcpy(pSacl, pAcl, pAcl->AclSize);
967 pAbs->Sacl = pSacl;
970 if (pRel->Control & SE_DACL_PRESENT)
972 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
973 memcpy(pDacl, pAcl, pAcl->AclSize);
974 pAbs->Dacl = pDacl;
977 if (pRel->Owner)
979 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
980 memcpy(pOwner, psid, RtlLengthSid(psid));
981 pAbs->Owner = pOwner;
984 if (pRel->Group)
986 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
987 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
988 pAbs->Group = pPrimaryGroup;
991 return status;
994 /******************************************************************************
995 * RtlGetControlSecurityDescriptor (NTDLL.@)
997 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
998 PSECURITY_DESCRIPTOR pSecurityDescriptor,
999 PSECURITY_DESCRIPTOR_CONTROL pControl,
1000 LPDWORD lpdwRevision)
1002 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1004 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1006 *lpdwRevision = lpsd->Revision;
1008 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1009 return STATUS_UNKNOWN_REVISION;
1011 *pControl = lpsd->Control;
1013 return STATUS_SUCCESS;
1017 /**************************************************************************
1018 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1020 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1021 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1022 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1023 PULONG BufferLength)
1025 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1027 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1028 SelfRelativeSecurityDescriptor, BufferLength);
1030 if (abs->Control & SE_SELF_RELATIVE)
1031 return STATUS_BAD_DESCRIPTOR_FORMAT;
1033 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1034 SelfRelativeSecurityDescriptor, BufferLength);
1039 * access control list's
1042 /**************************************************************************
1043 * RtlCreateAcl [NTDLL.@]
1045 * NOTES
1046 * This should return NTSTATUS
1048 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1050 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1052 if (rev!=ACL_REVISION)
1053 return STATUS_INVALID_PARAMETER;
1054 if (size<sizeof(ACL))
1055 return STATUS_BUFFER_TOO_SMALL;
1056 if (size>0xFFFF)
1057 return STATUS_INVALID_PARAMETER;
1059 memset(acl,'\0',sizeof(ACL));
1060 acl->AclRevision = rev;
1061 acl->AclSize = size;
1062 acl->AceCount = 0;
1063 return STATUS_SUCCESS;
1066 /**************************************************************************
1067 * RtlFirstFreeAce [NTDLL.@]
1068 * looks for the AceCount+1 ACE, and if it is still within the alloced
1069 * ACL, return a pointer to it
1071 BOOLEAN WINAPI RtlFirstFreeAce(
1072 PACL acl,
1073 PACE_HEADER *x)
1075 PACE_HEADER ace;
1076 int i;
1078 *x = 0;
1079 ace = (PACE_HEADER)(acl+1);
1080 for (i=0;i<acl->AceCount;i++) {
1081 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1082 return 0;
1083 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1085 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1086 return 0;
1087 *x = ace;
1088 return 1;
1091 /**************************************************************************
1092 * RtlAddAce [NTDLL.@]
1094 NTSTATUS WINAPI RtlAddAce(
1095 PACL acl,
1096 DWORD rev,
1097 DWORD xnrofaces,
1098 PACE_HEADER acestart,
1099 DWORD acelen)
1101 PACE_HEADER ace,targetace;
1102 int nrofaces;
1104 if (acl->AclRevision != ACL_REVISION)
1105 return STATUS_INVALID_PARAMETER;
1106 if (!RtlFirstFreeAce(acl,&targetace))
1107 return STATUS_INVALID_PARAMETER;
1108 nrofaces=0;ace=acestart;
1109 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1110 nrofaces++;
1111 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1113 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1114 return STATUS_INVALID_PARAMETER;
1115 memcpy((LPBYTE)targetace,acestart,acelen);
1116 acl->AceCount+=nrofaces;
1117 return STATUS_SUCCESS;
1120 /**************************************************************************
1121 * RtlDeleteAce [NTDLL.@]
1123 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1125 NTSTATUS status;
1126 PACE_HEADER pAce;
1128 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1130 if (STATUS_SUCCESS == status)
1132 PACE_HEADER pcAce;
1133 DWORD len = 0;
1135 /* skip over the ACE we are deleting */
1136 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1137 dwAceIndex++;
1139 /* calculate the length of the rest */
1140 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1142 len += pcAce->AceSize;
1143 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1146 /* slide them all backwards */
1147 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1148 pAcl->AceCount--;
1151 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1153 return status;
1156 /******************************************************************************
1157 * RtlAddAccessAllowedAce [NTDLL.@]
1159 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1160 IN OUT PACL pAcl,
1161 IN DWORD dwAceRevision,
1162 IN DWORD AccessMask,
1163 IN PSID pSid)
1165 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1168 /******************************************************************************
1169 * RtlAddAccessAllowedAceEx [NTDLL.@]
1171 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1172 IN OUT PACL pAcl,
1173 IN DWORD dwAceRevision,
1174 IN DWORD AceFlags,
1175 IN DWORD AccessMask,
1176 IN PSID pSid)
1178 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1180 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1181 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1184 /******************************************************************************
1185 * RtlAddAccessDeniedAce [NTDLL.@]
1187 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1188 IN OUT PACL pAcl,
1189 IN DWORD dwAceRevision,
1190 IN DWORD AccessMask,
1191 IN PSID pSid)
1193 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1196 /******************************************************************************
1197 * RtlAddAccessDeniedAceEx [NTDLL.@]
1199 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1200 IN OUT PACL pAcl,
1201 IN DWORD dwAceRevision,
1202 IN DWORD AceFlags,
1203 IN DWORD AccessMask,
1204 IN PSID pSid)
1206 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1208 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1209 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1212 /**************************************************************************
1213 * RtlAddAuditAccessAce [NTDLL.@]
1215 NTSTATUS WINAPI RtlAddAuditAccessAce(
1216 IN OUT PACL pAcl,
1217 IN DWORD dwAceRevision,
1218 IN DWORD dwAccessMask,
1219 IN PSID pSid,
1220 IN BOOL bAuditSuccess,
1221 IN BOOL bAuditFailure)
1223 DWORD dwAceFlags = 0;
1225 TRACE("(%p,%d,%d,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1226 pSid,bAuditSuccess,bAuditFailure);
1228 if (bAuditSuccess)
1229 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1231 if (bAuditFailure)
1232 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1234 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1235 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1238 /******************************************************************************
1239 * RtlValidAcl [NTDLL.@]
1241 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1243 BOOLEAN ret;
1244 TRACE("(%p)\n", pAcl);
1246 __TRY
1248 PACE_HEADER ace;
1249 int i;
1251 if (pAcl->AclRevision != ACL_REVISION)
1252 ret = FALSE;
1253 else
1255 ace = (PACE_HEADER)(pAcl+1);
1256 ret = TRUE;
1257 for (i=0;i<=pAcl->AceCount;i++)
1259 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1261 ret = FALSE;
1262 break;
1264 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1268 __EXCEPT_PAGE_FAULT
1270 WARN("(%p): invalid pointer!\n", pAcl);
1271 return 0;
1273 __ENDTRY
1274 return ret;
1277 /******************************************************************************
1278 * RtlGetAce [NTDLL.@]
1280 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1282 PACE_HEADER ace;
1284 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1286 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1287 return STATUS_INVALID_PARAMETER;
1289 ace = (PACE_HEADER)(pAcl + 1);
1290 for (;dwAceIndex;dwAceIndex--)
1291 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1293 *pAce = (LPVOID) ace;
1295 return STATUS_SUCCESS;
1299 * misc
1302 /******************************************************************************
1303 * RtlAdjustPrivilege [NTDLL.@]
1305 * Enables or disables a privilege from the calling thread or process.
1307 * PARAMS
1308 * Privilege [I] Privilege index to change.
1309 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1310 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1311 * Enabled [O] Whether privilege was previously enabled or disabled.
1313 * RETURNS
1314 * Success: STATUS_SUCCESS.
1315 * Failure: NTSTATUS code.
1317 * SEE ALSO
1318 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1321 NTSTATUS WINAPI
1322 RtlAdjustPrivilege(ULONG Privilege,
1323 BOOLEAN Enable,
1324 BOOLEAN CurrentThread,
1325 PBOOLEAN Enabled)
1327 TOKEN_PRIVILEGES NewState;
1328 TOKEN_PRIVILEGES OldState;
1329 ULONG ReturnLength;
1330 HANDLE TokenHandle;
1331 NTSTATUS Status;
1333 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1334 CurrentThread ? "TRUE" : "FALSE", Enabled);
1336 if (CurrentThread)
1338 Status = NtOpenThreadToken(GetCurrentThread(),
1339 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1340 FALSE,
1341 &TokenHandle);
1343 else
1345 Status = NtOpenProcessToken(GetCurrentProcess(),
1346 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1347 &TokenHandle);
1350 if (!NT_SUCCESS(Status))
1352 WARN("Retrieving token handle failed (Status %x)\n", Status);
1353 return Status;
1356 OldState.PrivilegeCount = 1;
1358 NewState.PrivilegeCount = 1;
1359 NewState.Privileges[0].Luid.LowPart = Privilege;
1360 NewState.Privileges[0].Luid.HighPart = 0;
1361 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1363 Status = NtAdjustPrivilegesToken(TokenHandle,
1364 FALSE,
1365 &NewState,
1366 sizeof(TOKEN_PRIVILEGES),
1367 &OldState,
1368 &ReturnLength);
1369 NtClose (TokenHandle);
1370 if (Status == STATUS_NOT_ALL_ASSIGNED)
1372 TRACE("Failed to assign all privileges\n");
1373 return STATUS_PRIVILEGE_NOT_HELD;
1375 if (!NT_SUCCESS(Status))
1377 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1378 return Status;
1381 if (OldState.PrivilegeCount == 0)
1382 *Enabled = Enable;
1383 else
1384 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1386 return STATUS_SUCCESS;
1389 /******************************************************************************
1390 * RtlImpersonateSelf [NTDLL.@]
1392 * Makes an impersonation token that represents the process user and assigns
1393 * to the current thread.
1395 * PARAMS
1396 * ImpersonationLevel [I] Level at which to impersonate.
1398 * RETURNS
1399 * Success: STATUS_SUCCESS.
1400 * Failure: NTSTATUS code.
1402 NTSTATUS WINAPI
1403 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1405 NTSTATUS Status;
1406 OBJECT_ATTRIBUTES ObjectAttributes;
1407 HANDLE ProcessToken;
1408 HANDLE ImpersonationToken;
1410 TRACE("(%08x)\n", ImpersonationLevel);
1412 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1413 &ProcessToken);
1414 if (Status != STATUS_SUCCESS)
1415 return Status;
1417 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1419 Status = NtDuplicateToken( ProcessToken,
1420 TOKEN_IMPERSONATE,
1421 &ObjectAttributes,
1422 ImpersonationLevel,
1423 TokenImpersonation,
1424 &ImpersonationToken );
1425 if (Status != STATUS_SUCCESS)
1427 NtClose( ProcessToken );
1428 return Status;
1431 Status = NtSetInformationThread( GetCurrentThread(),
1432 ThreadImpersonationToken,
1433 &ImpersonationToken,
1434 sizeof(ImpersonationToken) );
1436 NtClose( ImpersonationToken );
1437 NtClose( ProcessToken );
1439 return Status;
1442 /******************************************************************************
1443 * NtAccessCheck [NTDLL.@]
1444 * ZwAccessCheck [NTDLL.@]
1446 * Checks that a user represented by a token is allowed to access an object
1447 * represented by a security descriptor.
1449 * PARAMS
1450 * SecurityDescriptor [I] The security descriptor of the object to check.
1451 * ClientToken [I] Token of the user accessing the object.
1452 * DesiredAccess [I] The desired access to the object.
1453 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1454 * PrivilegeSet [I/O] Privileges used during the access check.
1455 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1456 * GrantedAccess [O] The actual access rights granted.
1457 * AccessStatus [O] The status of the access check.
1459 * RETURNS
1460 * NTSTATUS code.
1462 * NOTES
1463 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1464 * the maximum access rights allowed by the SD and returns them in
1465 * GrantedAccess.
1466 * The SecurityDescriptor must have a valid owner and groups present,
1467 * otherwise the function will fail.
1469 NTSTATUS WINAPI
1470 NtAccessCheck(
1471 PSECURITY_DESCRIPTOR SecurityDescriptor,
1472 HANDLE ClientToken,
1473 ACCESS_MASK DesiredAccess,
1474 PGENERIC_MAPPING GenericMapping,
1475 PPRIVILEGE_SET PrivilegeSet,
1476 PULONG ReturnLength,
1477 PULONG GrantedAccess,
1478 NTSTATUS *AccessStatus)
1480 NTSTATUS status;
1482 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1483 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1484 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1486 SERVER_START_REQ( access_check )
1488 struct security_descriptor sd;
1489 PSID owner;
1490 PSID group;
1491 PACL sacl;
1492 PACL dacl;
1493 BOOLEAN defaulted, present;
1494 DWORD revision;
1495 SECURITY_DESCRIPTOR_CONTROL control;
1497 req->handle = ClientToken;
1498 req->desired_access = DesiredAccess;
1499 req->mapping_read = GenericMapping->GenericRead;
1500 req->mapping_write = GenericMapping->GenericWrite;
1501 req->mapping_execute = GenericMapping->GenericExecute;
1502 req->mapping_all = GenericMapping->GenericAll;
1504 /* marshal security descriptor */
1505 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1506 sd.control = control & ~SE_SELF_RELATIVE;
1507 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1508 sd.owner_len = RtlLengthSid( owner );
1509 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1510 sd.group_len = RtlLengthSid( group );
1511 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1512 sd.sacl_len = (present ? sacl->AclSize : 0);
1513 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1514 sd.dacl_len = (present ? dacl->AclSize : 0);
1516 wine_server_add_data( req, &sd, sizeof(sd) );
1517 wine_server_add_data( req, owner, sd.owner_len );
1518 wine_server_add_data( req, group, sd.group_len );
1519 wine_server_add_data( req, sacl, sd.sacl_len );
1520 wine_server_add_data( req, dacl, sd.dacl_len );
1522 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1524 status = wine_server_call( req );
1526 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1527 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1529 if (status == STATUS_SUCCESS)
1531 *AccessStatus = reply->access_status;
1532 *GrantedAccess = reply->access_granted;
1535 SERVER_END_REQ;
1537 return status;
1540 /******************************************************************************
1541 * NtSetSecurityObject [NTDLL.@]
1542 * ZwSetSecurityObject [NTDLL.@]
1544 * Sets specified parts of the object's security descriptor.
1546 * PARAMS
1547 * Handle [I] Handle to the object to change security descriptor of.
1548 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1549 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1551 * RETURNS
1552 * NTSTATUS code.
1555 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1556 SECURITY_INFORMATION SecurityInformation,
1557 PSECURITY_DESCRIPTOR SecurityDescriptor)
1559 NTSTATUS status;
1560 struct security_descriptor sd;
1561 PACL dacl, sacl;
1562 PSID owner, group;
1563 BOOLEAN defaulted, present;
1564 DWORD revision;
1565 SECURITY_DESCRIPTOR_CONTROL control;
1567 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1569 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1571 memset( &sd, 0, sizeof(sd) );
1572 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1573 if (status != STATUS_SUCCESS) return status;
1574 sd.control = control & ~SE_SELF_RELATIVE;
1576 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1578 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1579 if (status != STATUS_SUCCESS) return status;
1580 if (!(sd.owner_len = RtlLengthSid( owner )))
1581 return STATUS_INVALID_SECURITY_DESCR;
1584 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1586 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1587 if (status != STATUS_SUCCESS) return status;
1588 if (!(sd.group_len = RtlLengthSid( group )))
1589 return STATUS_INVALID_SECURITY_DESCR;
1592 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1594 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1595 if (status != STATUS_SUCCESS) return status;
1596 sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1597 sd.control |= SE_SACL_PRESENT;
1600 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1602 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1603 if (status != STATUS_SUCCESS) return status;
1604 sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1605 sd.control |= SE_DACL_PRESENT;
1608 SERVER_START_REQ( set_security_object )
1610 req->handle = Handle;
1611 req->security_info = SecurityInformation;
1613 wine_server_add_data( req, &sd, sizeof(sd) );
1614 wine_server_add_data( req, owner, sd.owner_len );
1615 wine_server_add_data( req, group, sd.group_len );
1616 wine_server_add_data( req, sacl, sd.sacl_len );
1617 wine_server_add_data( req, dacl, sd.dacl_len );
1618 status = wine_server_call( req );
1620 SERVER_END_REQ;
1622 return status;
1625 /******************************************************************************
1626 * RtlConvertSidToUnicodeString (NTDLL.@)
1628 * The returned SID is used to access the USER registry hive usually
1630 * the native function returns something like
1631 * "S-1-5-21-0000000000-000000000-0000000000-500";
1633 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1634 PUNICODE_STRING String,
1635 PSID pSid,
1636 BOOLEAN AllocateString)
1638 static const WCHAR formatW[] = {'-','%','u',0};
1639 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1640 WCHAR *p = buffer;
1641 const SID *sid = (const SID *)pSid;
1642 DWORD i, len;
1644 *p++ = 'S';
1645 p += sprintfW( p, formatW, sid->Revision );
1646 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1647 sid->IdentifierAuthority.Value[4] ),
1648 MAKEWORD( sid->IdentifierAuthority.Value[3],
1649 sid->IdentifierAuthority.Value[2] )));
1650 for (i = 0; i < sid->SubAuthorityCount; i++)
1651 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1653 len = (p + 1 - buffer) * sizeof(WCHAR);
1655 String->Length = len - sizeof(WCHAR);
1656 if (AllocateString)
1658 String->MaximumLength = len;
1659 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1660 return STATUS_NO_MEMORY;
1662 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1664 memcpy( String->Buffer, buffer, len );
1665 return STATUS_SUCCESS;
1668 /******************************************************************************
1669 * RtlQueryInformationAcl (NTDLL.@)
1671 NTSTATUS WINAPI RtlQueryInformationAcl(
1672 PACL pAcl,
1673 LPVOID pAclInformation,
1674 DWORD nAclInformationLength,
1675 ACL_INFORMATION_CLASS dwAclInformationClass)
1677 NTSTATUS status = STATUS_SUCCESS;
1679 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1680 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1682 switch (dwAclInformationClass)
1684 case AclRevisionInformation:
1686 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1688 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1689 status = STATUS_INVALID_PARAMETER;
1690 else
1691 paclrev->AclRevision = pAcl->AclRevision;
1693 break;
1696 case AclSizeInformation:
1698 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1700 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1701 status = STATUS_INVALID_PARAMETER;
1702 else
1704 INT i;
1705 PACE_HEADER ace;
1707 paclsize->AceCount = pAcl->AceCount;
1709 paclsize->AclBytesInUse = 0;
1710 ace = (PACE_HEADER) (pAcl + 1);
1712 for (i = 0; i < pAcl->AceCount; i++)
1714 paclsize->AclBytesInUse += ace->AceSize;
1715 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1718 if (pAcl->AclSize < paclsize->AclBytesInUse)
1720 WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1721 paclsize->AclBytesFree = 0;
1722 paclsize->AclBytesInUse = pAcl->AclSize;
1724 else
1725 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1728 break;
1731 default:
1732 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1733 status = STATUS_INVALID_PARAMETER;
1736 return status;