wined3d: Add modifier support to tex and friends.
[wine/wine-gecko.git] / dlls / ntdll / sec.c
blob950b9dd2b856e6fe1407dfccd497d34d746dcc13
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "ntdll_misc.h"
39 #include "wine/exception.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
50 /* helper function to retrieve active length of an ACL */
51 static size_t acl_bytesInUse(PACL pAcl)
53 int i;
54 size_t bytesInUse = sizeof(ACL);
55 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
56 for (i = 0; i < pAcl->AceCount; i++)
58 bytesInUse += ace->AceSize;
59 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
61 return bytesInUse;
64 /* helper function to copy an ACL */
65 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
67 DWORD size;
69 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
70 return FALSE;
72 size = pSourceAcl->AclSize;
73 if (nDestinationAclLength < size)
74 return FALSE;
76 memmove(pDestinationAcl, pSourceAcl, size);
77 return TRUE;
80 /* generically adds an ACE to an ACL */
81 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
82 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
84 ACE_HEADER *pAceHeader;
85 DWORD dwLengthSid;
86 DWORD dwAceSize;
87 DWORD *pAccessMask;
88 DWORD *pSidStart;
90 if (!RtlValidSid(pSid))
91 return STATUS_INVALID_SID;
93 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
94 return STATUS_REVISION_MISMATCH;
96 if (!RtlValidAcl(pAcl))
97 return STATUS_INVALID_ACL;
99 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
100 return STATUS_INVALID_ACL;
102 if (!pAceHeader)
103 return STATUS_ALLOTTED_SPACE_EXCEEDED;
105 /* calculate generic size of the ACE */
106 dwLengthSid = RtlLengthSid(pSid);
107 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
108 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
109 return STATUS_ALLOTTED_SPACE_EXCEEDED;
111 /* fill the new ACE */
112 pAceHeader->AceType = dwAceType;
113 pAceHeader->AceFlags = dwAceFlags;
114 pAceHeader->AceSize = dwAceSize;
116 /* skip past the ACE_HEADER of the ACE */
117 pAccessMask = (DWORD *)(pAceHeader + 1);
118 *pAccessMask = dwAccessMask;
120 /* skip past ACE->Mask */
121 pSidStart = pAccessMask + 1;
122 RtlCopySid(dwLengthSid, pSidStart, pSid);
124 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
125 pAcl->AceCount++;
127 return STATUS_SUCCESS;
131 * SID FUNCTIONS
134 /******************************************************************************
135 * RtlAllocateAndInitializeSid [NTDLL.@]
138 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
139 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
140 BYTE nSubAuthorityCount,
141 DWORD nSubAuthority0, DWORD nSubAuthority1,
142 DWORD nSubAuthority2, DWORD nSubAuthority3,
143 DWORD nSubAuthority4, DWORD nSubAuthority5,
144 DWORD nSubAuthority6, DWORD nSubAuthority7,
145 PSID *pSid )
147 SID *tmp_sid;
149 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
150 pIdentifierAuthority,nSubAuthorityCount,
151 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
152 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
154 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
156 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
157 RtlLengthRequiredSid(nSubAuthorityCount))))
158 return STATUS_NO_MEMORY;
160 tmp_sid->Revision = SID_REVISION;
162 if (pIdentifierAuthority)
163 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
164 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
166 switch( nSubAuthorityCount )
168 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
169 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
170 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
171 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
172 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
173 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
174 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
175 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
176 break;
178 *pSid = tmp_sid;
179 return STATUS_SUCCESS;
182 /******************************************************************************
183 * RtlEqualSid [NTDLL.@]
185 * Determine if two SIDs are equal.
187 * PARAMS
188 * pSid1 [I] Source SID
189 * pSid2 [I] SID to compare with
191 * RETURNS
192 * TRUE, if pSid1 is equal to pSid2,
193 * FALSE otherwise.
195 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
197 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
198 return FALSE;
200 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
201 return FALSE;
203 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
204 return FALSE;
206 return TRUE;
209 /******************************************************************************
210 * RtlEqualPrefixSid [NTDLL.@]
212 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
214 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
215 return FALSE;
217 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
218 return FALSE;
220 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
221 return FALSE;
223 return TRUE;
227 /******************************************************************************
228 * RtlFreeSid [NTDLL.@]
230 * Free the resources used by a SID.
232 * PARAMS
233 * pSid [I] SID to Free.
235 * RETURNS
236 * STATUS_SUCCESS.
238 DWORD WINAPI RtlFreeSid(PSID pSid)
240 TRACE("(%p)\n", pSid);
241 RtlFreeHeap( GetProcessHeap(), 0, pSid );
242 return STATUS_SUCCESS;
245 /**************************************************************************
246 * RtlLengthRequiredSid [NTDLL.@]
248 * Determine the amount of memory a SID will use
250 * PARAMS
251 * nrofsubauths [I] Number of Sub Authorities in the SID.
253 * RETURNS
254 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
256 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
258 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
261 /**************************************************************************
262 * RtlLengthSid [NTDLL.@]
264 * Determine the amount of memory a SID is using
266 * PARAMS
267 * pSid [I] SID to get the size of.
269 * RETURNS
270 * The size, in bytes, of pSid.
272 DWORD WINAPI RtlLengthSid(PSID pSid)
274 TRACE("sid=%p\n",pSid);
275 if (!pSid) return 0;
276 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
279 /**************************************************************************
280 * RtlInitializeSid [NTDLL.@]
282 * Initialise a SID.
284 * PARAMS
285 * pSid [I] SID to initialise
286 * pIdentifierAuthority [I] Identifier Authority
287 * nSubAuthorityCount [I] Number of Sub Authorities
289 * RETURNS
290 * Success: TRUE. pSid is initialised with the details given.
291 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
293 BOOL WINAPI RtlInitializeSid(
294 PSID pSid,
295 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
296 BYTE nSubAuthorityCount)
298 int i;
299 SID* pisid=pSid;
301 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
302 return FALSE;
304 pisid->Revision = SID_REVISION;
305 pisid->SubAuthorityCount = nSubAuthorityCount;
306 if (pIdentifierAuthority)
307 pisid->IdentifierAuthority = *pIdentifierAuthority;
309 for (i = 0; i < nSubAuthorityCount; i++)
310 *RtlSubAuthoritySid(pSid, i) = 0;
312 return TRUE;
315 /**************************************************************************
316 * RtlSubAuthoritySid [NTDLL.@]
318 * Return the Sub Authority of a SID
320 * PARAMS
321 * pSid [I] SID to get the Sub Authority from.
322 * nSubAuthority [I] Sub Authority number.
324 * RETURNS
325 * A pointer to The Sub Authority value of pSid.
327 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
329 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
332 /**************************************************************************
333 * RtlIdentifierAuthoritySid [NTDLL.@]
335 * Return the Identifier Authority of a SID.
337 * PARAMS
338 * pSid [I] SID to get the Identifier Authority from.
340 * RETURNS
341 * A pointer to the Identifier Authority value of pSid.
343 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
345 return &(((SID*)pSid)->IdentifierAuthority);
348 /**************************************************************************
349 * RtlSubAuthorityCountSid [NTDLL.@]
351 * Get the number of Sub Authorities in a SID.
353 * PARAMS
354 * pSid [I] SID to get the count from.
356 * RETURNS
357 * A pointer to the Sub Authority count of pSid.
359 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
361 return &(((SID*)pSid)->SubAuthorityCount);
364 /**************************************************************************
365 * RtlCopySid [NTDLL.@]
367 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
369 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
370 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
371 return FALSE;
373 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
374 return FALSE;
376 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
377 return TRUE;
379 /******************************************************************************
380 * RtlValidSid [NTDLL.@]
382 * Determine if a SID is valid.
384 * PARAMS
385 * pSid [I] SID to check
387 * RETURNS
388 * TRUE if pSid is valid,
389 * FALSE otherwise.
391 BOOLEAN WINAPI RtlValidSid( PSID pSid )
393 BOOL ret;
394 __TRY
396 ret = TRUE;
397 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
398 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
400 ret = FALSE;
403 __EXCEPT_PAGE_FAULT
405 WARN("(%p): invalid pointer!\n", pSid);
406 return FALSE;
408 __ENDTRY
409 return ret;
414 * security descriptor functions
417 /**************************************************************************
418 * RtlCreateSecurityDescriptor [NTDLL.@]
420 * Initialise a SECURITY_DESCRIPTOR.
422 * PARAMS
423 * lpsd [O] Descriptor to initialise.
424 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
426 * RETURNS
427 * Success: STATUS_SUCCESS.
428 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
430 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
431 PSECURITY_DESCRIPTOR lpsd,
432 DWORD rev)
434 if (rev!=SECURITY_DESCRIPTOR_REVISION)
435 return STATUS_UNKNOWN_REVISION;
436 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
437 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
438 return STATUS_SUCCESS;
441 /**************************************************************************
442 * RtlCopySecurityDescriptor [NTDLL.@]
444 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
446 * PARAMS
447 * pSourceSD [O] SD to copy from.
448 * pDestinationSD [I] Destination SD.
450 * RETURNS
451 * Success: STATUS_SUCCESS.
452 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
454 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
456 PSID Owner, Group;
457 PACL Dacl, Sacl;
458 DWORD length;
460 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
462 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
463 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
465 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
466 return STATUS_UNKNOWN_REVISION;
468 *dst = *src;
469 if (src->Owner)
471 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
472 length = RtlLengthSid( Owner );
473 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
475 if (src->Group)
477 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
478 length = RtlLengthSid( Group );
479 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
481 if (src->Control & SE_SACL_PRESENT)
483 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
484 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
486 if (src->Control & SE_DACL_PRESENT)
488 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
489 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
492 else
494 SECURITY_DESCRIPTOR *src = pSourceSD;
495 SECURITY_DESCRIPTOR *dst = pDestinationSD;
497 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
498 return STATUS_UNKNOWN_REVISION;
500 *dst = *src;
501 if (src->Owner)
503 length = RtlLengthSid( src->Owner );
504 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
505 RtlCopySid(length, dst->Owner, src->Owner);
507 if (src->Group)
509 length = RtlLengthSid( src->Group );
510 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
511 RtlCopySid(length, dst->Group, src->Group);
513 if (src->Control & SE_SACL_PRESENT)
515 length = src->Sacl->AclSize;
516 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
517 copy_acl(length, dst->Sacl, src->Sacl);
519 if (src->Control & SE_DACL_PRESENT)
521 length = src->Dacl->AclSize;
522 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
523 copy_acl(length, dst->Dacl, src->Dacl);
527 return STATUS_SUCCESS;
530 /**************************************************************************
531 * RtlValidSecurityDescriptor [NTDLL.@]
533 * Determine if a SECURITY_DESCRIPTOR is valid.
535 * PARAMS
536 * SecurityDescriptor [I] Descriptor to check.
538 * RETURNS
539 * Success: STATUS_SUCCESS.
540 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
542 NTSTATUS WINAPI RtlValidSecurityDescriptor(
543 PSECURITY_DESCRIPTOR SecurityDescriptor)
545 if ( ! SecurityDescriptor )
546 return STATUS_INVALID_SECURITY_DESCR;
547 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
548 return STATUS_UNKNOWN_REVISION;
550 return STATUS_SUCCESS;
553 /**************************************************************************
554 * RtlLengthSecurityDescriptor [NTDLL.@]
556 ULONG WINAPI RtlLengthSecurityDescriptor(
557 PSECURITY_DESCRIPTOR pSecurityDescriptor)
559 ULONG size;
561 if ( pSecurityDescriptor == NULL )
562 return 0;
564 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
566 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
567 size = sizeof(*sd);
568 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
569 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
570 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
571 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
572 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
573 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
575 else
577 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
578 size = sizeof(*sd);
579 if (sd->Owner) size += RtlLengthSid( sd->Owner );
580 if (sd->Group) size += RtlLengthSid( sd->Group );
581 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
582 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
584 return size;
587 /******************************************************************************
588 * RtlGetDaclSecurityDescriptor [NTDLL.@]
591 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
592 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
593 OUT PBOOLEAN lpbDaclPresent,
594 OUT PACL *pDacl,
595 OUT PBOOLEAN lpbDaclDefaulted)
597 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
599 TRACE("(%p,%p,%p,%p)\n",
600 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
602 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
603 return STATUS_UNKNOWN_REVISION ;
605 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
607 if ( SE_SELF_RELATIVE & lpsd->Control)
608 *pDacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Dacl );
609 else
610 *pDacl = lpsd->Dacl;
612 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
614 else
616 *pDacl = NULL;
617 *lpbDaclDefaulted = 0;
620 return STATUS_SUCCESS;
623 /**************************************************************************
624 * RtlSetDaclSecurityDescriptor [NTDLL.@]
626 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
627 PSECURITY_DESCRIPTOR pSecurityDescriptor,
628 BOOLEAN daclpresent,
629 PACL dacl,
630 BOOLEAN dacldefaulted )
632 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
634 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
635 return STATUS_UNKNOWN_REVISION;
636 if (lpsd->Control & SE_SELF_RELATIVE)
637 return STATUS_INVALID_SECURITY_DESCR;
639 if (!daclpresent)
641 lpsd->Control &= ~SE_DACL_PRESENT;
642 return STATUS_SUCCESS;
645 lpsd->Control |= SE_DACL_PRESENT;
646 lpsd->Dacl = dacl;
648 if (dacldefaulted)
649 lpsd->Control |= SE_DACL_DEFAULTED;
650 else
651 lpsd->Control &= ~SE_DACL_DEFAULTED;
653 return STATUS_SUCCESS;
656 /******************************************************************************
657 * RtlGetSaclSecurityDescriptor [NTDLL.@]
660 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
661 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
662 OUT PBOOLEAN lpbSaclPresent,
663 OUT PACL *pSacl,
664 OUT PBOOLEAN lpbSaclDefaulted)
666 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
668 TRACE("(%p,%p,%p,%p)\n",
669 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
671 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
672 return STATUS_UNKNOWN_REVISION;
674 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
676 if (SE_SELF_RELATIVE & lpsd->Control)
677 *pSacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Sacl );
678 else
679 *pSacl = lpsd->Sacl;
681 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
683 return STATUS_SUCCESS;
686 /**************************************************************************
687 * RtlSetSaclSecurityDescriptor [NTDLL.@]
689 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
690 PSECURITY_DESCRIPTOR pSecurityDescriptor,
691 BOOLEAN saclpresent,
692 PACL sacl,
693 BOOLEAN sacldefaulted)
695 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
697 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
698 return STATUS_UNKNOWN_REVISION;
699 if (lpsd->Control & SE_SELF_RELATIVE)
700 return STATUS_INVALID_SECURITY_DESCR;
701 if (!saclpresent) {
702 lpsd->Control &= ~SE_SACL_PRESENT;
703 return 0;
705 lpsd->Control |= SE_SACL_PRESENT;
706 lpsd->Sacl = sacl;
707 if (sacldefaulted)
708 lpsd->Control |= SE_SACL_DEFAULTED;
709 else
710 lpsd->Control &= ~SE_SACL_DEFAULTED;
711 return STATUS_SUCCESS;
714 /**************************************************************************
715 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
717 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
718 PSECURITY_DESCRIPTOR pSecurityDescriptor,
719 PSID *Owner,
720 PBOOLEAN OwnerDefaulted)
722 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
724 if ( !lpsd || !Owner || !OwnerDefaulted )
725 return STATUS_INVALID_PARAMETER;
727 if ( lpsd->Control & SE_OWNER_DEFAULTED )
728 *OwnerDefaulted = TRUE;
729 else
730 *OwnerDefaulted = FALSE;
732 if (lpsd->Control & SE_SELF_RELATIVE)
734 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
735 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
736 else *Owner = NULL;
738 else
739 *Owner = lpsd->Owner;
741 return STATUS_SUCCESS;
744 /**************************************************************************
745 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
747 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
748 PSECURITY_DESCRIPTOR pSecurityDescriptor,
749 PSID owner,
750 BOOLEAN ownerdefaulted)
752 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
754 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
755 return STATUS_UNKNOWN_REVISION;
756 if (lpsd->Control & SE_SELF_RELATIVE)
757 return STATUS_INVALID_SECURITY_DESCR;
759 lpsd->Owner = owner;
760 if (ownerdefaulted)
761 lpsd->Control |= SE_OWNER_DEFAULTED;
762 else
763 lpsd->Control &= ~SE_OWNER_DEFAULTED;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetGroupSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
772 PSID group,
773 BOOLEAN groupdefaulted)
775 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
777 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
778 return STATUS_UNKNOWN_REVISION;
779 if (lpsd->Control & SE_SELF_RELATIVE)
780 return STATUS_INVALID_SECURITY_DESCR;
782 lpsd->Group = group;
783 if (groupdefaulted)
784 lpsd->Control |= SE_GROUP_DEFAULTED;
785 else
786 lpsd->Control &= ~SE_GROUP_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlGetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
795 PSID *Group,
796 PBOOLEAN GroupDefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if ( !lpsd || !Group || !GroupDefaulted )
801 return STATUS_INVALID_PARAMETER;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
805 else
806 *GroupDefaulted = FALSE;
808 if (lpsd->Control & SE_SELF_RELATIVE)
810 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
811 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
812 else *Group = NULL;
814 else
815 *Group = lpsd->Group;
817 return STATUS_SUCCESS;
820 /**************************************************************************
821 * RtlMakeSelfRelativeSD [NTDLL.@]
823 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
824 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
825 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
826 IN OUT LPDWORD lpdwBufferLength)
828 DWORD offsetRel;
829 ULONG length;
830 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
831 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
833 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
834 lpdwBufferLength ? *lpdwBufferLength: -1);
836 if (!lpdwBufferLength || !pAbs)
837 return STATUS_INVALID_PARAMETER;
839 length = RtlLengthSecurityDescriptor(pAbs);
840 if (*lpdwBufferLength < length)
842 *lpdwBufferLength = length;
843 return STATUS_BUFFER_TOO_SMALL;
846 if (!pRel)
847 return STATUS_INVALID_PARAMETER;
849 if (pAbs->Control & SE_SELF_RELATIVE)
851 memcpy(pRel, pAbs, length);
852 return STATUS_SUCCESS;
855 pRel->Revision = pAbs->Revision;
856 pRel->Sbz1 = pAbs->Sbz1;
857 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
859 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
860 if (pAbs->Owner)
862 pRel->Owner = offsetRel;
863 length = RtlLengthSid(pAbs->Owner);
864 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
865 offsetRel += length;
867 else
869 pRel->Owner = 0;
872 if (pAbs->Group)
874 pRel->Group = offsetRel;
875 length = RtlLengthSid(pAbs->Group);
876 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
877 offsetRel += length;
879 else
881 pRel->Group = 0;
884 if (pAbs->Sacl)
886 pRel->Sacl = offsetRel;
887 length = pAbs->Sacl->AclSize;
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
889 offsetRel += length;
891 else
893 pRel->Sacl = 0;
896 if (pAbs->Dacl)
898 pRel->Dacl = offsetRel;
899 length = pAbs->Dacl->AclSize;
900 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
902 else
904 pRel->Dacl = 0;
907 return STATUS_SUCCESS;
911 /**************************************************************************
912 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
914 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
915 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
916 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
917 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
918 OUT PACL pDacl,
919 OUT LPDWORD lpdwDaclSize,
920 OUT PACL pSacl,
921 OUT LPDWORD lpdwSaclSize,
922 OUT PSID pOwner,
923 OUT LPDWORD lpdwOwnerSize,
924 OUT PSID pPrimaryGroup,
925 OUT LPDWORD lpdwPrimaryGroupSize)
927 NTSTATUS status = STATUS_SUCCESS;
928 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
929 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
931 if (!pRel ||
932 !lpdwAbsoluteSecurityDescriptorSize ||
933 !lpdwDaclSize ||
934 !lpdwSaclSize ||
935 !lpdwOwnerSize ||
936 !lpdwPrimaryGroupSize ||
937 ~pRel->Control & SE_SELF_RELATIVE)
938 return STATUS_INVALID_PARAMETER;
940 /* Confirm buffers are sufficiently large */
941 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
943 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
944 status = STATUS_BUFFER_TOO_SMALL;
947 if (pRel->Control & SE_DACL_PRESENT &&
948 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
950 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
951 status = STATUS_BUFFER_TOO_SMALL;
954 if (pRel->Control & SE_SACL_PRESENT &&
955 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
957 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (pRel->Owner &&
962 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
964 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
965 status = STATUS_BUFFER_TOO_SMALL;
968 if (pRel->Group &&
969 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
971 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (status != STATUS_SUCCESS)
976 return status;
978 /* Copy structures, and clear the ones we don't set */
979 pAbs->Revision = pRel->Revision;
980 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
981 pAbs->Sacl = NULL;
982 pAbs->Dacl = NULL;
983 pAbs->Owner = NULL;
984 pAbs->Group = NULL;
986 if (pRel->Control & SE_SACL_PRESENT)
988 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
990 memcpy(pSacl, pAcl, pAcl->AclSize);
991 pAbs->Sacl = pSacl;
994 if (pRel->Control & SE_DACL_PRESENT)
996 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
997 memcpy(pDacl, pAcl, pAcl->AclSize);
998 pAbs->Dacl = pDacl;
1001 if (pRel->Owner)
1003 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1004 memcpy(pOwner, psid, RtlLengthSid(psid));
1005 pAbs->Owner = pOwner;
1008 if (pRel->Group)
1010 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1011 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1012 pAbs->Group = pPrimaryGroup;
1015 return status;
1018 /******************************************************************************
1019 * RtlGetControlSecurityDescriptor (NTDLL.@)
1021 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1022 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1023 PSECURITY_DESCRIPTOR_CONTROL pControl,
1024 LPDWORD lpdwRevision)
1026 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1028 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1030 *lpdwRevision = lpsd->Revision;
1032 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1033 return STATUS_UNKNOWN_REVISION;
1035 *pControl = lpsd->Control;
1037 return STATUS_SUCCESS;
1040 /******************************************************************************
1041 * RtlSetControlSecurityDescriptor (NTDLL.@)
1043 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1044 PSECURITY_DESCRIPTOR SecurityDescriptor,
1045 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1046 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1048 SECURITY_DESCRIPTOR_CONTROL const immutable
1049 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1050 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1051 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1052 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1055 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1057 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1058 ControlBitsOfInterest, ControlBitsToSet);
1060 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1061 return STATUS_INVALID_PARAMETER;
1063 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1064 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1066 return STATUS_SUCCESS;
1070 /**************************************************************************
1071 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1073 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1074 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1075 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1076 PULONG BufferLength)
1078 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1080 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1081 SelfRelativeSecurityDescriptor, BufferLength);
1083 if (abs->Control & SE_SELF_RELATIVE)
1084 return STATUS_BAD_DESCRIPTOR_FORMAT;
1086 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1087 SelfRelativeSecurityDescriptor, BufferLength);
1092 * access control list's
1095 /**************************************************************************
1096 * RtlCreateAcl [NTDLL.@]
1098 * NOTES
1099 * This should return NTSTATUS
1101 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1103 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1105 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1106 return STATUS_INVALID_PARAMETER;
1107 if (size<sizeof(ACL))
1108 return STATUS_BUFFER_TOO_SMALL;
1109 if (size>0xFFFF)
1110 return STATUS_INVALID_PARAMETER;
1112 memset(acl,'\0',sizeof(ACL));
1113 acl->AclRevision = rev;
1114 acl->AclSize = size;
1115 acl->AceCount = 0;
1116 return STATUS_SUCCESS;
1119 /**************************************************************************
1120 * RtlFirstFreeAce [NTDLL.@]
1121 * looks for the AceCount+1 ACE, and if it is still within the alloced
1122 * ACL, return a pointer to it
1124 BOOLEAN WINAPI RtlFirstFreeAce(
1125 PACL acl,
1126 PACE_HEADER *x)
1128 PACE_HEADER ace;
1129 int i;
1131 *x = 0;
1132 ace = (PACE_HEADER)(acl+1);
1133 for (i=0;i<acl->AceCount;i++) {
1134 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1135 return 0;
1136 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1138 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1139 return 0;
1140 *x = ace;
1141 return 1;
1144 /**************************************************************************
1145 * RtlAddAce [NTDLL.@]
1147 NTSTATUS WINAPI RtlAddAce(
1148 PACL acl,
1149 DWORD rev,
1150 DWORD xnrofaces,
1151 PACE_HEADER acestart,
1152 DWORD acelen)
1154 PACE_HEADER ace,targetace;
1155 int nrofaces;
1157 if (acl->AclRevision != ACL_REVISION)
1158 return STATUS_INVALID_PARAMETER;
1159 if (!RtlFirstFreeAce(acl,&targetace))
1160 return STATUS_INVALID_PARAMETER;
1161 nrofaces=0;ace=acestart;
1162 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1163 nrofaces++;
1164 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1166 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1167 return STATUS_INVALID_PARAMETER;
1168 memcpy(targetace,acestart,acelen);
1169 acl->AceCount+=nrofaces;
1170 return STATUS_SUCCESS;
1173 /**************************************************************************
1174 * RtlDeleteAce [NTDLL.@]
1176 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1178 NTSTATUS status;
1179 PACE_HEADER pAce;
1181 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1183 if (STATUS_SUCCESS == status)
1185 PACE_HEADER pcAce;
1186 DWORD len = 0;
1188 /* skip over the ACE we are deleting */
1189 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1190 dwAceIndex++;
1192 /* calculate the length of the rest */
1193 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1195 len += pcAce->AceSize;
1196 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1199 /* slide them all backwards */
1200 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1201 pAcl->AceCount--;
1204 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1206 return status;
1209 /******************************************************************************
1210 * RtlAddAccessAllowedAce [NTDLL.@]
1212 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1213 IN OUT PACL pAcl,
1214 IN DWORD dwAceRevision,
1215 IN DWORD AccessMask,
1216 IN PSID pSid)
1218 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1221 /******************************************************************************
1222 * RtlAddAccessAllowedAceEx [NTDLL.@]
1224 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1225 IN OUT PACL pAcl,
1226 IN DWORD dwAceRevision,
1227 IN DWORD AceFlags,
1228 IN DWORD AccessMask,
1229 IN PSID pSid)
1231 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1233 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1234 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1237 /******************************************************************************
1238 * RtlAddAccessDeniedAce [NTDLL.@]
1240 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1241 IN OUT PACL pAcl,
1242 IN DWORD dwAceRevision,
1243 IN DWORD AccessMask,
1244 IN PSID pSid)
1246 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1249 /******************************************************************************
1250 * RtlAddAccessDeniedAceEx [NTDLL.@]
1252 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1253 IN OUT PACL pAcl,
1254 IN DWORD dwAceRevision,
1255 IN DWORD AceFlags,
1256 IN DWORD AccessMask,
1257 IN PSID pSid)
1259 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1261 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1262 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1265 /**************************************************************************
1266 * RtlAddAuditAccessAce [NTDLL.@]
1268 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1269 IN OUT PACL pAcl,
1270 IN DWORD dwAceRevision,
1271 IN DWORD dwAceFlags,
1272 IN DWORD dwAccessMask,
1273 IN PSID pSid,
1274 IN BOOL bAuditSuccess,
1275 IN BOOL bAuditFailure)
1277 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1278 pSid,bAuditSuccess,bAuditFailure);
1280 if (bAuditSuccess)
1281 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1283 if (bAuditFailure)
1284 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1286 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1287 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1290 /**************************************************************************
1291 * RtlAddAuditAccessAce [NTDLL.@]
1293 NTSTATUS WINAPI RtlAddAuditAccessAce(
1294 IN OUT PACL pAcl,
1295 IN DWORD dwAceRevision,
1296 IN DWORD dwAccessMask,
1297 IN PSID pSid,
1298 IN BOOL bAuditSuccess,
1299 IN BOOL bAuditFailure)
1301 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1304 /******************************************************************************
1305 * RtlValidAcl [NTDLL.@]
1307 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1309 BOOLEAN ret;
1310 TRACE("(%p)\n", pAcl);
1312 __TRY
1314 PACE_HEADER ace;
1315 int i;
1317 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1318 pAcl->AclRevision > MAX_ACL_REVISION)
1319 ret = FALSE;
1320 else
1322 ace = (PACE_HEADER)(pAcl+1);
1323 ret = TRUE;
1324 for (i=0;i<=pAcl->AceCount;i++)
1326 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1328 ret = FALSE;
1329 break;
1331 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1335 __EXCEPT_PAGE_FAULT
1337 WARN("(%p): invalid pointer!\n", pAcl);
1338 return 0;
1340 __ENDTRY
1341 return ret;
1344 /******************************************************************************
1345 * RtlGetAce [NTDLL.@]
1347 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1349 PACE_HEADER ace;
1351 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1353 if (dwAceIndex >= pAcl->AceCount)
1354 return STATUS_INVALID_PARAMETER;
1356 ace = (PACE_HEADER)(pAcl + 1);
1357 for (;dwAceIndex;dwAceIndex--)
1358 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1360 *pAce = ace;
1362 return STATUS_SUCCESS;
1366 * misc
1369 /******************************************************************************
1370 * RtlAdjustPrivilege [NTDLL.@]
1372 * Enables or disables a privilege from the calling thread or process.
1374 * PARAMS
1375 * Privilege [I] Privilege index to change.
1376 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1377 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1378 * Enabled [O] Whether privilege was previously enabled or disabled.
1380 * RETURNS
1381 * Success: STATUS_SUCCESS.
1382 * Failure: NTSTATUS code.
1384 * SEE ALSO
1385 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1388 NTSTATUS WINAPI
1389 RtlAdjustPrivilege(ULONG Privilege,
1390 BOOLEAN Enable,
1391 BOOLEAN CurrentThread,
1392 PBOOLEAN Enabled)
1394 TOKEN_PRIVILEGES NewState;
1395 TOKEN_PRIVILEGES OldState;
1396 ULONG ReturnLength;
1397 HANDLE TokenHandle;
1398 NTSTATUS Status;
1400 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1401 CurrentThread ? "TRUE" : "FALSE", Enabled);
1403 if (CurrentThread)
1405 Status = NtOpenThreadToken(GetCurrentThread(),
1406 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1407 FALSE,
1408 &TokenHandle);
1410 else
1412 Status = NtOpenProcessToken(GetCurrentProcess(),
1413 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1414 &TokenHandle);
1417 if (!NT_SUCCESS(Status))
1419 WARN("Retrieving token handle failed (Status %x)\n", Status);
1420 return Status;
1423 OldState.PrivilegeCount = 1;
1425 NewState.PrivilegeCount = 1;
1426 NewState.Privileges[0].Luid.LowPart = Privilege;
1427 NewState.Privileges[0].Luid.HighPart = 0;
1428 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1430 Status = NtAdjustPrivilegesToken(TokenHandle,
1431 FALSE,
1432 &NewState,
1433 sizeof(TOKEN_PRIVILEGES),
1434 &OldState,
1435 &ReturnLength);
1436 NtClose (TokenHandle);
1437 if (Status == STATUS_NOT_ALL_ASSIGNED)
1439 TRACE("Failed to assign all privileges\n");
1440 return STATUS_PRIVILEGE_NOT_HELD;
1442 if (!NT_SUCCESS(Status))
1444 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1445 return Status;
1448 if (OldState.PrivilegeCount == 0)
1449 *Enabled = Enable;
1450 else
1451 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1453 return STATUS_SUCCESS;
1456 /******************************************************************************
1457 * RtlImpersonateSelf [NTDLL.@]
1459 * Makes an impersonation token that represents the process user and assigns
1460 * to the current thread.
1462 * PARAMS
1463 * ImpersonationLevel [I] Level at which to impersonate.
1465 * RETURNS
1466 * Success: STATUS_SUCCESS.
1467 * Failure: NTSTATUS code.
1469 NTSTATUS WINAPI
1470 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1472 NTSTATUS Status;
1473 OBJECT_ATTRIBUTES ObjectAttributes;
1474 HANDLE ProcessToken;
1475 HANDLE ImpersonationToken;
1477 TRACE("(%08x)\n", ImpersonationLevel);
1479 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1480 &ProcessToken);
1481 if (Status != STATUS_SUCCESS)
1482 return Status;
1484 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1486 Status = NtDuplicateToken( ProcessToken,
1487 TOKEN_IMPERSONATE,
1488 &ObjectAttributes,
1489 ImpersonationLevel,
1490 TokenImpersonation,
1491 &ImpersonationToken );
1492 if (Status != STATUS_SUCCESS)
1494 NtClose( ProcessToken );
1495 return Status;
1498 Status = NtSetInformationThread( GetCurrentThread(),
1499 ThreadImpersonationToken,
1500 &ImpersonationToken,
1501 sizeof(ImpersonationToken) );
1503 NtClose( ImpersonationToken );
1504 NtClose( ProcessToken );
1506 return Status;
1509 /******************************************************************************
1510 * NtAccessCheck [NTDLL.@]
1511 * ZwAccessCheck [NTDLL.@]
1513 * Checks that a user represented by a token is allowed to access an object
1514 * represented by a security descriptor.
1516 * PARAMS
1517 * SecurityDescriptor [I] The security descriptor of the object to check.
1518 * ClientToken [I] Token of the user accessing the object.
1519 * DesiredAccess [I] The desired access to the object.
1520 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1521 * PrivilegeSet [I/O] Privileges used during the access check.
1522 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1523 * GrantedAccess [O] The actual access rights granted.
1524 * AccessStatus [O] The status of the access check.
1526 * RETURNS
1527 * NTSTATUS code.
1529 * NOTES
1530 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1531 * the maximum access rights allowed by the SD and returns them in
1532 * GrantedAccess.
1533 * The SecurityDescriptor must have a valid owner and groups present,
1534 * otherwise the function will fail.
1536 NTSTATUS WINAPI
1537 NtAccessCheck(
1538 PSECURITY_DESCRIPTOR SecurityDescriptor,
1539 HANDLE ClientToken,
1540 ACCESS_MASK DesiredAccess,
1541 PGENERIC_MAPPING GenericMapping,
1542 PPRIVILEGE_SET PrivilegeSet,
1543 PULONG ReturnLength,
1544 PULONG GrantedAccess,
1545 NTSTATUS *AccessStatus)
1547 NTSTATUS status;
1549 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1550 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1551 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1553 if (!PrivilegeSet || !ReturnLength)
1554 return STATUS_ACCESS_VIOLATION;
1556 SERVER_START_REQ( access_check )
1558 struct security_descriptor sd;
1559 PSID owner;
1560 PSID group;
1561 PACL sacl;
1562 PACL dacl;
1563 BOOLEAN defaulted, present;
1564 DWORD revision;
1565 SECURITY_DESCRIPTOR_CONTROL control;
1567 req->handle = wine_server_obj_handle( ClientToken );
1568 req->desired_access = DesiredAccess;
1569 req->mapping_read = GenericMapping->GenericRead;
1570 req->mapping_write = GenericMapping->GenericWrite;
1571 req->mapping_execute = GenericMapping->GenericExecute;
1572 req->mapping_all = GenericMapping->GenericAll;
1574 /* marshal security descriptor */
1575 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1576 sd.control = control & ~SE_SELF_RELATIVE;
1577 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1578 sd.owner_len = RtlLengthSid( owner );
1579 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1580 sd.group_len = RtlLengthSid( group );
1581 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1582 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1583 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1584 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1586 wine_server_add_data( req, &sd, sizeof(sd) );
1587 wine_server_add_data( req, owner, sd.owner_len );
1588 wine_server_add_data( req, group, sd.group_len );
1589 wine_server_add_data( req, sacl, sd.sacl_len );
1590 wine_server_add_data( req, dacl, sd.dacl_len );
1592 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1594 status = wine_server_call( req );
1596 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1597 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1599 if (status == STATUS_SUCCESS)
1601 *AccessStatus = reply->access_status;
1602 *GrantedAccess = reply->access_granted;
1605 SERVER_END_REQ;
1607 return status;
1610 /******************************************************************************
1611 * NtSetSecurityObject [NTDLL.@]
1612 * ZwSetSecurityObject [NTDLL.@]
1614 * Sets specified parts of the object's security descriptor.
1616 * PARAMS
1617 * Handle [I] Handle to the object to change security descriptor of.
1618 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1619 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1621 * RETURNS
1622 * NTSTATUS code.
1625 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1626 SECURITY_INFORMATION SecurityInformation,
1627 PSECURITY_DESCRIPTOR SecurityDescriptor)
1629 NTSTATUS status;
1630 struct security_descriptor sd;
1631 PACL dacl = NULL, sacl = NULL;
1632 PSID owner = NULL, group = NULL;
1633 BOOLEAN defaulted, present;
1634 DWORD revision;
1635 SECURITY_DESCRIPTOR_CONTROL control;
1637 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1639 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1641 memset( &sd, 0, sizeof(sd) );
1642 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1643 if (status != STATUS_SUCCESS) return status;
1644 sd.control = control & ~SE_SELF_RELATIVE;
1646 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1648 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1649 if (status != STATUS_SUCCESS) return status;
1650 if (!(sd.owner_len = RtlLengthSid( owner )))
1651 return STATUS_INVALID_SECURITY_DESCR;
1654 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1656 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1657 if (status != STATUS_SUCCESS) return status;
1658 if (!(sd.group_len = RtlLengthSid( group )))
1659 return STATUS_INVALID_SECURITY_DESCR;
1662 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1664 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1665 if (status != STATUS_SUCCESS) return status;
1666 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1667 sd.control |= SE_SACL_PRESENT;
1670 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1672 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1673 if (status != STATUS_SUCCESS) return status;
1674 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1675 sd.control |= SE_DACL_PRESENT;
1678 SERVER_START_REQ( set_security_object )
1680 req->handle = wine_server_obj_handle( Handle );
1681 req->security_info = SecurityInformation;
1683 wine_server_add_data( req, &sd, sizeof(sd) );
1684 wine_server_add_data( req, owner, sd.owner_len );
1685 wine_server_add_data( req, group, sd.group_len );
1686 wine_server_add_data( req, sacl, sd.sacl_len );
1687 wine_server_add_data( req, dacl, sd.dacl_len );
1688 status = wine_server_call( req );
1690 SERVER_END_REQ;
1692 return status;
1695 /******************************************************************************
1696 * RtlConvertSidToUnicodeString (NTDLL.@)
1698 * The returned SID is used to access the USER registry hive usually
1700 * the native function returns something like
1701 * "S-1-5-21-0000000000-000000000-0000000000-500";
1703 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1704 PUNICODE_STRING String,
1705 PSID pSid,
1706 BOOLEAN AllocateString)
1708 static const WCHAR formatW[] = {'-','%','u',0};
1709 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1710 WCHAR *p = buffer;
1711 const SID *sid = pSid;
1712 DWORD i, len;
1714 *p++ = 'S';
1715 p += sprintfW( p, formatW, sid->Revision );
1716 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1717 sid->IdentifierAuthority.Value[4] ),
1718 MAKEWORD( sid->IdentifierAuthority.Value[3],
1719 sid->IdentifierAuthority.Value[2] )));
1720 for (i = 0; i < sid->SubAuthorityCount; i++)
1721 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1723 len = (p + 1 - buffer) * sizeof(WCHAR);
1725 String->Length = len - sizeof(WCHAR);
1726 if (AllocateString)
1728 String->MaximumLength = len;
1729 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1730 return STATUS_NO_MEMORY;
1732 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1734 memcpy( String->Buffer, buffer, len );
1735 return STATUS_SUCCESS;
1738 /******************************************************************************
1739 * RtlQueryInformationAcl (NTDLL.@)
1741 NTSTATUS WINAPI RtlQueryInformationAcl(
1742 PACL pAcl,
1743 LPVOID pAclInformation,
1744 DWORD nAclInformationLength,
1745 ACL_INFORMATION_CLASS dwAclInformationClass)
1747 NTSTATUS status = STATUS_SUCCESS;
1749 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1750 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1752 switch (dwAclInformationClass)
1754 case AclRevisionInformation:
1756 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1758 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1759 status = STATUS_INVALID_PARAMETER;
1760 else
1761 paclrev->AclRevision = pAcl->AclRevision;
1763 break;
1766 case AclSizeInformation:
1768 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1770 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1771 status = STATUS_INVALID_PARAMETER;
1772 else
1774 paclsize->AceCount = pAcl->AceCount;
1775 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1776 if (pAcl->AclSize < paclsize->AclBytesInUse)
1778 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1779 paclsize->AclBytesFree = 0;
1780 paclsize->AclBytesInUse = pAcl->AclSize;
1782 else
1783 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1786 break;
1789 default:
1790 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1791 status = STATUS_INVALID_PARAMETER;
1794 return status;