wined3d: Recognize SM4 ftou opcode.
[wine.git] / dlls / ntdll / sec.c
blob125c86eb86a086301b285e0bff87af316fceb76a
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 /* fall through */
170 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
171 /* fall through */
172 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
173 /* fall through */
174 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
175 /* fall through */
176 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
177 /* fall through */
178 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
179 /* fall through */
180 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
181 /* fall through */
182 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
183 break;
185 *pSid = tmp_sid;
186 return STATUS_SUCCESS;
189 /******************************************************************************
190 * RtlEqualSid [NTDLL.@]
192 * Determine if two SIDs are equal.
194 * PARAMS
195 * pSid1 [I] Source SID
196 * pSid2 [I] SID to compare with
198 * RETURNS
199 * TRUE, if pSid1 is equal to pSid2,
200 * FALSE otherwise.
202 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
204 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
205 return FALSE;
207 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
208 return FALSE;
210 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
211 return FALSE;
213 return TRUE;
216 /******************************************************************************
217 * RtlEqualPrefixSid [NTDLL.@]
219 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
221 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
222 return FALSE;
224 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
225 return FALSE;
227 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
228 return FALSE;
230 return TRUE;
234 /******************************************************************************
235 * RtlFreeSid [NTDLL.@]
237 * Free the resources used by a SID.
239 * PARAMS
240 * pSid [I] SID to Free.
242 * RETURNS
243 * STATUS_SUCCESS.
245 DWORD WINAPI RtlFreeSid(PSID pSid)
247 TRACE("(%p)\n", pSid);
248 RtlFreeHeap( GetProcessHeap(), 0, pSid );
249 return STATUS_SUCCESS;
252 /**************************************************************************
253 * RtlLengthRequiredSid [NTDLL.@]
255 * Determine the amount of memory a SID will use
257 * PARAMS
258 * nrofsubauths [I] Number of Sub Authorities in the SID.
260 * RETURNS
261 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
263 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
265 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
268 /**************************************************************************
269 * RtlLengthSid [NTDLL.@]
271 * Determine the amount of memory a SID is using
273 * PARAMS
274 * pSid [I] SID to get the size of.
276 * RETURNS
277 * The size, in bytes, of pSid.
279 DWORD WINAPI RtlLengthSid(PSID pSid)
281 TRACE("sid=%p\n",pSid);
282 if (!pSid) return 0;
283 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
286 /**************************************************************************
287 * RtlInitializeSid [NTDLL.@]
289 * Initialise a SID.
291 * PARAMS
292 * pSid [I] SID to initialise
293 * pIdentifierAuthority [I] Identifier Authority
294 * nSubAuthorityCount [I] Number of Sub Authorities
296 * RETURNS
297 * Success: TRUE. pSid is initialised with the details given.
298 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
300 BOOL WINAPI RtlInitializeSid(
301 PSID pSid,
302 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
303 BYTE nSubAuthorityCount)
305 int i;
306 SID* pisid=pSid;
308 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
309 return FALSE;
311 pisid->Revision = SID_REVISION;
312 pisid->SubAuthorityCount = nSubAuthorityCount;
313 if (pIdentifierAuthority)
314 pisid->IdentifierAuthority = *pIdentifierAuthority;
316 for (i = 0; i < nSubAuthorityCount; i++)
317 *RtlSubAuthoritySid(pSid, i) = 0;
319 return TRUE;
322 /**************************************************************************
323 * RtlSubAuthoritySid [NTDLL.@]
325 * Return the Sub Authority of a SID
327 * PARAMS
328 * pSid [I] SID to get the Sub Authority from.
329 * nSubAuthority [I] Sub Authority number.
331 * RETURNS
332 * A pointer to The Sub Authority value of pSid.
334 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
336 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
339 /**************************************************************************
340 * RtlIdentifierAuthoritySid [NTDLL.@]
342 * Return the Identifier Authority of a SID.
344 * PARAMS
345 * pSid [I] SID to get the Identifier Authority from.
347 * RETURNS
348 * A pointer to the Identifier Authority value of pSid.
350 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
352 return &(((SID*)pSid)->IdentifierAuthority);
355 /**************************************************************************
356 * RtlSubAuthorityCountSid [NTDLL.@]
358 * Get the number of Sub Authorities in a SID.
360 * PARAMS
361 * pSid [I] SID to get the count from.
363 * RETURNS
364 * A pointer to the Sub Authority count of pSid.
366 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
368 return &(((SID*)pSid)->SubAuthorityCount);
371 /**************************************************************************
372 * RtlCopySid [NTDLL.@]
374 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
376 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
377 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
378 return FALSE;
380 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
381 return FALSE;
383 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
384 return TRUE;
386 /******************************************************************************
387 * RtlValidSid [NTDLL.@]
389 * Determine if a SID is valid.
391 * PARAMS
392 * pSid [I] SID to check
394 * RETURNS
395 * TRUE if pSid is valid,
396 * FALSE otherwise.
398 BOOLEAN WINAPI RtlValidSid( PSID pSid )
400 BOOL ret;
401 __TRY
403 ret = TRUE;
404 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
405 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
407 ret = FALSE;
410 __EXCEPT_PAGE_FAULT
412 WARN("(%p): invalid pointer!\n", pSid);
413 return FALSE;
415 __ENDTRY
416 return ret;
421 * security descriptor functions
424 /**************************************************************************
425 * RtlCreateSecurityDescriptor [NTDLL.@]
427 * Initialise a SECURITY_DESCRIPTOR.
429 * PARAMS
430 * lpsd [O] Descriptor to initialise.
431 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
433 * RETURNS
434 * Success: STATUS_SUCCESS.
435 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
437 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
438 PSECURITY_DESCRIPTOR lpsd,
439 DWORD rev)
441 if (rev!=SECURITY_DESCRIPTOR_REVISION)
442 return STATUS_UNKNOWN_REVISION;
443 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
444 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
445 return STATUS_SUCCESS;
448 /**************************************************************************
449 * RtlCopySecurityDescriptor [NTDLL.@]
451 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
453 * PARAMS
454 * pSourceSD [O] SD to copy from.
455 * pDestinationSD [I] Destination SD.
457 * RETURNS
458 * Success: STATUS_SUCCESS.
459 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
461 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
463 PSID Owner, Group;
464 PACL Dacl, Sacl;
465 DWORD length;
467 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
469 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
470 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
472 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
473 return STATUS_UNKNOWN_REVISION;
475 *dst = *src;
476 if (src->Owner)
478 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
479 length = RtlLengthSid( Owner );
480 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
482 if (src->Group)
484 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
485 length = RtlLengthSid( Group );
486 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
488 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
490 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
491 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
493 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
495 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
496 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
499 else
501 SECURITY_DESCRIPTOR *src = pSourceSD;
502 SECURITY_DESCRIPTOR *dst = pDestinationSD;
504 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
505 return STATUS_UNKNOWN_REVISION;
507 *dst = *src;
508 if (src->Owner)
510 length = RtlLengthSid( src->Owner );
511 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
512 RtlCopySid(length, dst->Owner, src->Owner);
514 if (src->Group)
516 length = RtlLengthSid( src->Group );
517 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 RtlCopySid(length, dst->Group, src->Group);
520 if (src->Control & SE_SACL_PRESENT)
522 length = src->Sacl->AclSize;
523 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
524 copy_acl(length, dst->Sacl, src->Sacl);
526 if (src->Control & SE_DACL_PRESENT)
528 length = src->Dacl->AclSize;
529 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
530 copy_acl(length, dst->Dacl, src->Dacl);
534 return STATUS_SUCCESS;
537 /**************************************************************************
538 * RtlValidSecurityDescriptor [NTDLL.@]
540 * Determine if a SECURITY_DESCRIPTOR is valid.
542 * PARAMS
543 * SecurityDescriptor [I] Descriptor to check.
545 * RETURNS
546 * Success: STATUS_SUCCESS.
547 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
549 NTSTATUS WINAPI RtlValidSecurityDescriptor(
550 PSECURITY_DESCRIPTOR SecurityDescriptor)
552 if ( ! SecurityDescriptor )
553 return STATUS_INVALID_SECURITY_DESCR;
554 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
555 return STATUS_UNKNOWN_REVISION;
557 return STATUS_SUCCESS;
560 /**************************************************************************
561 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
563 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
564 ULONG length, SECURITY_INFORMATION info)
566 FIXME("%p,%u,%d: semi-stub\n", descriptor, length, info);
567 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
570 /**************************************************************************
571 * RtlLengthSecurityDescriptor [NTDLL.@]
573 ULONG WINAPI RtlLengthSecurityDescriptor(
574 PSECURITY_DESCRIPTOR pSecurityDescriptor)
576 ULONG size;
578 if ( pSecurityDescriptor == NULL )
579 return 0;
581 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
583 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
584 size = sizeof(*sd);
585 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
586 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
587 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
588 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
590 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
592 else
594 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
595 size = sizeof(*sd);
596 if (sd->Owner) size += RtlLengthSid( sd->Owner );
597 if (sd->Group) size += RtlLengthSid( sd->Group );
598 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
599 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
601 return size;
604 /******************************************************************************
605 * RtlGetDaclSecurityDescriptor [NTDLL.@]
608 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
609 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
610 OUT PBOOLEAN lpbDaclPresent,
611 OUT PACL *pDacl,
612 OUT PBOOLEAN lpbDaclDefaulted)
614 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
616 TRACE("(%p,%p,%p,%p)\n",
617 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
619 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
620 return STATUS_UNKNOWN_REVISION ;
622 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
624 if (lpsd->Control & SE_SELF_RELATIVE)
626 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
627 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
628 else *pDacl = NULL;
630 else *pDacl = lpsd->Dacl;
632 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
634 else
636 *pDacl = NULL;
637 *lpbDaclDefaulted = 0;
640 return STATUS_SUCCESS;
643 /**************************************************************************
644 * RtlSetDaclSecurityDescriptor [NTDLL.@]
646 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
647 PSECURITY_DESCRIPTOR pSecurityDescriptor,
648 BOOLEAN daclpresent,
649 PACL dacl,
650 BOOLEAN dacldefaulted )
652 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
654 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
655 return STATUS_UNKNOWN_REVISION;
656 if (lpsd->Control & SE_SELF_RELATIVE)
657 return STATUS_INVALID_SECURITY_DESCR;
659 if (!daclpresent)
661 lpsd->Control &= ~SE_DACL_PRESENT;
662 return STATUS_SUCCESS;
665 lpsd->Control |= SE_DACL_PRESENT;
666 lpsd->Dacl = dacl;
668 if (dacldefaulted)
669 lpsd->Control |= SE_DACL_DEFAULTED;
670 else
671 lpsd->Control &= ~SE_DACL_DEFAULTED;
673 return STATUS_SUCCESS;
676 /******************************************************************************
677 * RtlGetSaclSecurityDescriptor [NTDLL.@]
680 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
681 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
682 OUT PBOOLEAN lpbSaclPresent,
683 OUT PACL *pSacl,
684 OUT PBOOLEAN lpbSaclDefaulted)
686 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
688 TRACE("(%p,%p,%p,%p)\n",
689 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
691 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
692 return STATUS_UNKNOWN_REVISION;
694 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
696 if (lpsd->Control & SE_SELF_RELATIVE)
698 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
699 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
700 else *pSacl = NULL;
702 else *pSacl = lpsd->Sacl;
704 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
706 return STATUS_SUCCESS;
709 /**************************************************************************
710 * RtlSetSaclSecurityDescriptor [NTDLL.@]
712 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
713 PSECURITY_DESCRIPTOR pSecurityDescriptor,
714 BOOLEAN saclpresent,
715 PACL sacl,
716 BOOLEAN sacldefaulted)
718 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
720 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
721 return STATUS_UNKNOWN_REVISION;
722 if (lpsd->Control & SE_SELF_RELATIVE)
723 return STATUS_INVALID_SECURITY_DESCR;
724 if (!saclpresent) {
725 lpsd->Control &= ~SE_SACL_PRESENT;
726 return 0;
728 lpsd->Control |= SE_SACL_PRESENT;
729 lpsd->Sacl = sacl;
730 if (sacldefaulted)
731 lpsd->Control |= SE_SACL_DEFAULTED;
732 else
733 lpsd->Control &= ~SE_SACL_DEFAULTED;
734 return STATUS_SUCCESS;
737 /**************************************************************************
738 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
740 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
741 PSECURITY_DESCRIPTOR pSecurityDescriptor,
742 PSID *Owner,
743 PBOOLEAN OwnerDefaulted)
745 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
747 if ( !lpsd || !Owner || !OwnerDefaulted )
748 return STATUS_INVALID_PARAMETER;
750 if ( lpsd->Control & SE_OWNER_DEFAULTED )
751 *OwnerDefaulted = TRUE;
752 else
753 *OwnerDefaulted = FALSE;
755 if (lpsd->Control & SE_SELF_RELATIVE)
757 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
758 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
759 else *Owner = NULL;
761 else
762 *Owner = lpsd->Owner;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
772 PSID owner,
773 BOOLEAN ownerdefaulted)
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->Owner = owner;
783 if (ownerdefaulted)
784 lpsd->Control |= SE_OWNER_DEFAULTED;
785 else
786 lpsd->Control &= ~SE_OWNER_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlSetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
795 PSID group,
796 BOOLEAN groupdefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
801 return STATUS_UNKNOWN_REVISION;
802 if (lpsd->Control & SE_SELF_RELATIVE)
803 return STATUS_INVALID_SECURITY_DESCR;
805 lpsd->Group = group;
806 if (groupdefaulted)
807 lpsd->Control |= SE_GROUP_DEFAULTED;
808 else
809 lpsd->Control &= ~SE_GROUP_DEFAULTED;
810 return STATUS_SUCCESS;
813 /**************************************************************************
814 * RtlGetGroupSecurityDescriptor [NTDLL.@]
816 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
817 PSECURITY_DESCRIPTOR pSecurityDescriptor,
818 PSID *Group,
819 PBOOLEAN GroupDefaulted)
821 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
823 if ( !lpsd || !Group || !GroupDefaulted )
824 return STATUS_INVALID_PARAMETER;
826 if ( lpsd->Control & SE_GROUP_DEFAULTED )
827 *GroupDefaulted = TRUE;
828 else
829 *GroupDefaulted = FALSE;
831 if (lpsd->Control & SE_SELF_RELATIVE)
833 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
834 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
835 else *Group = NULL;
837 else
838 *Group = lpsd->Group;
840 return STATUS_SUCCESS;
843 /**************************************************************************
844 * RtlMakeSelfRelativeSD [NTDLL.@]
846 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
847 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
848 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
849 IN OUT LPDWORD lpdwBufferLength)
851 DWORD offsetRel;
852 ULONG length;
853 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
854 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
856 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
857 lpdwBufferLength ? *lpdwBufferLength: -1);
859 if (!lpdwBufferLength || !pAbs)
860 return STATUS_INVALID_PARAMETER;
862 length = RtlLengthSecurityDescriptor(pAbs);
863 if (*lpdwBufferLength < length)
865 *lpdwBufferLength = length;
866 return STATUS_BUFFER_TOO_SMALL;
869 if (!pRel)
870 return STATUS_INVALID_PARAMETER;
872 if (pAbs->Control & SE_SELF_RELATIVE)
874 memcpy(pRel, pAbs, length);
875 return STATUS_SUCCESS;
878 pRel->Revision = pAbs->Revision;
879 pRel->Sbz1 = pAbs->Sbz1;
880 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
882 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
883 if (pAbs->Owner)
885 pRel->Owner = offsetRel;
886 length = RtlLengthSid(pAbs->Owner);
887 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
888 offsetRel += length;
890 else
892 pRel->Owner = 0;
895 if (pAbs->Group)
897 pRel->Group = offsetRel;
898 length = RtlLengthSid(pAbs->Group);
899 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
900 offsetRel += length;
902 else
904 pRel->Group = 0;
907 if (pAbs->Sacl)
909 pRel->Sacl = offsetRel;
910 length = pAbs->Sacl->AclSize;
911 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
912 offsetRel += length;
914 else
916 pRel->Sacl = 0;
919 if (pAbs->Dacl)
921 pRel->Dacl = offsetRel;
922 length = pAbs->Dacl->AclSize;
923 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
925 else
927 pRel->Dacl = 0;
930 return STATUS_SUCCESS;
934 /**************************************************************************
935 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
937 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
938 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
939 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
940 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
941 OUT PACL pDacl,
942 OUT LPDWORD lpdwDaclSize,
943 OUT PACL pSacl,
944 OUT LPDWORD lpdwSaclSize,
945 OUT PSID pOwner,
946 OUT LPDWORD lpdwOwnerSize,
947 OUT PSID pPrimaryGroup,
948 OUT LPDWORD lpdwPrimaryGroupSize)
950 NTSTATUS status = STATUS_SUCCESS;
951 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
952 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
954 if (!pRel ||
955 !lpdwAbsoluteSecurityDescriptorSize ||
956 !lpdwDaclSize ||
957 !lpdwSaclSize ||
958 !lpdwOwnerSize ||
959 !lpdwPrimaryGroupSize ||
960 ~pRel->Control & SE_SELF_RELATIVE)
961 return STATUS_INVALID_PARAMETER;
963 /* Confirm buffers are sufficiently large */
964 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
966 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
967 status = STATUS_BUFFER_TOO_SMALL;
970 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
971 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
973 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
974 status = STATUS_BUFFER_TOO_SMALL;
977 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
978 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
980 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
981 status = STATUS_BUFFER_TOO_SMALL;
984 if (pRel->Owner &&
985 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
987 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
988 status = STATUS_BUFFER_TOO_SMALL;
991 if (pRel->Group &&
992 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
994 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
995 status = STATUS_BUFFER_TOO_SMALL;
998 if (status != STATUS_SUCCESS)
999 return status;
1001 /* Copy structures, and clear the ones we don't set */
1002 pAbs->Revision = pRel->Revision;
1003 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
1004 pAbs->Sacl = NULL;
1005 pAbs->Dacl = NULL;
1006 pAbs->Owner = NULL;
1007 pAbs->Group = NULL;
1009 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1011 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1013 memcpy(pSacl, pAcl, pAcl->AclSize);
1014 pAbs->Sacl = pSacl;
1017 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1019 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1020 memcpy(pDacl, pAcl, pAcl->AclSize);
1021 pAbs->Dacl = pDacl;
1024 if (pRel->Owner)
1026 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1027 memcpy(pOwner, psid, RtlLengthSid(psid));
1028 pAbs->Owner = pOwner;
1031 if (pRel->Group)
1033 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1034 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1035 pAbs->Group = pPrimaryGroup;
1038 return status;
1041 /******************************************************************************
1042 * RtlGetControlSecurityDescriptor (NTDLL.@)
1044 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1045 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1046 PSECURITY_DESCRIPTOR_CONTROL pControl,
1047 LPDWORD lpdwRevision)
1049 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1051 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1053 *lpdwRevision = lpsd->Revision;
1055 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1056 return STATUS_UNKNOWN_REVISION;
1058 *pControl = lpsd->Control;
1060 return STATUS_SUCCESS;
1063 /******************************************************************************
1064 * RtlSetControlSecurityDescriptor (NTDLL.@)
1066 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1067 PSECURITY_DESCRIPTOR SecurityDescriptor,
1068 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1069 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1071 SECURITY_DESCRIPTOR_CONTROL const immutable
1072 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1073 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1074 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1075 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1078 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1080 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1081 ControlBitsOfInterest, ControlBitsToSet);
1083 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1084 return STATUS_INVALID_PARAMETER;
1086 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1087 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1089 return STATUS_SUCCESS;
1093 /**************************************************************************
1094 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1096 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1097 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1098 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1099 PULONG BufferLength)
1101 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1103 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1104 SelfRelativeSecurityDescriptor, BufferLength);
1106 if (abs->Control & SE_SELF_RELATIVE)
1107 return STATUS_BAD_DESCRIPTOR_FORMAT;
1109 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1110 SelfRelativeSecurityDescriptor, BufferLength);
1115 * access control list's
1118 /**************************************************************************
1119 * RtlCreateAcl [NTDLL.@]
1121 * NOTES
1122 * This should return NTSTATUS
1124 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1126 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1128 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1129 return STATUS_INVALID_PARAMETER;
1130 if (size<sizeof(ACL))
1131 return STATUS_BUFFER_TOO_SMALL;
1132 if (size>0xFFFF)
1133 return STATUS_INVALID_PARAMETER;
1135 memset(acl,'\0',sizeof(ACL));
1136 acl->AclRevision = rev;
1137 acl->AclSize = size;
1138 acl->AceCount = 0;
1139 return STATUS_SUCCESS;
1142 /**************************************************************************
1143 * RtlFirstFreeAce [NTDLL.@]
1144 * looks for the AceCount+1 ACE, and if it is still within the alloced
1145 * ACL, return a pointer to it
1147 BOOLEAN WINAPI RtlFirstFreeAce(
1148 PACL acl,
1149 PACE_HEADER *x)
1151 PACE_HEADER ace;
1152 int i;
1154 *x = 0;
1155 ace = (PACE_HEADER)(acl+1);
1156 for (i=0;i<acl->AceCount;i++) {
1157 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1158 return FALSE;
1159 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1161 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1162 return FALSE;
1163 *x = ace;
1164 return TRUE;
1167 /**************************************************************************
1168 * RtlAddAce [NTDLL.@]
1170 NTSTATUS WINAPI RtlAddAce(
1171 PACL acl,
1172 DWORD rev,
1173 DWORD xnrofaces,
1174 PACE_HEADER acestart,
1175 DWORD acelen)
1177 PACE_HEADER ace,targetace;
1178 int nrofaces;
1180 if (!RtlValidAcl(acl))
1181 return STATUS_INVALID_PARAMETER;
1182 if (!RtlFirstFreeAce(acl,&targetace))
1183 return STATUS_INVALID_PARAMETER;
1184 nrofaces=0;ace=acestart;
1185 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1186 nrofaces++;
1187 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1189 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1190 return STATUS_INVALID_PARAMETER;
1191 memcpy(targetace,acestart,acelen);
1192 acl->AceCount+=nrofaces;
1193 if (rev > acl->AclRevision)
1194 acl->AclRevision = rev;
1195 return STATUS_SUCCESS;
1198 /**************************************************************************
1199 * RtlDeleteAce [NTDLL.@]
1201 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1203 NTSTATUS status;
1204 PACE_HEADER pAce;
1206 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1208 if (STATUS_SUCCESS == status)
1210 PACE_HEADER pcAce;
1211 DWORD len = 0;
1213 /* skip over the ACE we are deleting */
1214 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1215 dwAceIndex++;
1217 /* calculate the length of the rest */
1218 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1220 len += pcAce->AceSize;
1221 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1224 /* slide them all backwards */
1225 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1226 pAcl->AceCount--;
1229 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1231 return status;
1234 /******************************************************************************
1235 * RtlAddAccessAllowedAce [NTDLL.@]
1237 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1238 IN OUT PACL pAcl,
1239 IN DWORD dwAceRevision,
1240 IN DWORD AccessMask,
1241 IN PSID pSid)
1243 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1246 /******************************************************************************
1247 * RtlAddAccessAllowedAceEx [NTDLL.@]
1249 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1250 IN OUT PACL pAcl,
1251 IN DWORD dwAceRevision,
1252 IN DWORD AceFlags,
1253 IN DWORD AccessMask,
1254 IN PSID pSid)
1256 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1258 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1259 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1262 /******************************************************************************
1263 * RtlAddAccessDeniedAce [NTDLL.@]
1265 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1266 IN OUT PACL pAcl,
1267 IN DWORD dwAceRevision,
1268 IN DWORD AccessMask,
1269 IN PSID pSid)
1271 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1274 /******************************************************************************
1275 * RtlAddAccessDeniedAceEx [NTDLL.@]
1277 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1278 IN OUT PACL pAcl,
1279 IN DWORD dwAceRevision,
1280 IN DWORD AceFlags,
1281 IN DWORD AccessMask,
1282 IN PSID pSid)
1284 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1286 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1287 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1290 /**************************************************************************
1291 * RtlAddAuditAccessAce [NTDLL.@]
1293 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1294 IN OUT PACL pAcl,
1295 IN DWORD dwAceRevision,
1296 IN DWORD dwAceFlags,
1297 IN DWORD dwAccessMask,
1298 IN PSID pSid,
1299 IN BOOL bAuditSuccess,
1300 IN BOOL bAuditFailure)
1302 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1303 pSid,bAuditSuccess,bAuditFailure);
1305 if (bAuditSuccess)
1306 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1308 if (bAuditFailure)
1309 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1311 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1312 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1315 /**************************************************************************
1316 * RtlAddAuditAccessAce [NTDLL.@]
1318 NTSTATUS WINAPI RtlAddAuditAccessAce(
1319 IN OUT PACL pAcl,
1320 IN DWORD dwAceRevision,
1321 IN DWORD dwAccessMask,
1322 IN PSID pSid,
1323 IN BOOL bAuditSuccess,
1324 IN BOOL bAuditFailure)
1326 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1329 /******************************************************************************
1330 * RtlValidAcl [NTDLL.@]
1332 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1334 BOOLEAN ret;
1335 TRACE("(%p)\n", pAcl);
1337 __TRY
1339 PACE_HEADER ace;
1340 int i;
1342 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1343 pAcl->AclRevision > MAX_ACL_REVISION)
1344 ret = FALSE;
1345 else
1347 ace = (PACE_HEADER)(pAcl+1);
1348 ret = TRUE;
1349 for (i=0;i<=pAcl->AceCount;i++)
1351 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1353 ret = FALSE;
1354 break;
1356 if (i != pAcl->AceCount)
1357 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1361 __EXCEPT_PAGE_FAULT
1363 WARN("(%p): invalid pointer!\n", pAcl);
1364 return FALSE;
1366 __ENDTRY
1367 return ret;
1370 /******************************************************************************
1371 * RtlGetAce [NTDLL.@]
1373 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1375 PACE_HEADER ace;
1377 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1379 if (dwAceIndex >= pAcl->AceCount)
1380 return STATUS_INVALID_PARAMETER;
1382 ace = (PACE_HEADER)(pAcl + 1);
1383 for (;dwAceIndex;dwAceIndex--)
1384 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1386 *pAce = ace;
1388 return STATUS_SUCCESS;
1392 * misc
1395 /******************************************************************************
1396 * RtlAdjustPrivilege [NTDLL.@]
1398 * Enables or disables a privilege from the calling thread or process.
1400 * PARAMS
1401 * Privilege [I] Privilege index to change.
1402 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1403 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1404 * Enabled [O] Whether privilege was previously enabled or disabled.
1406 * RETURNS
1407 * Success: STATUS_SUCCESS.
1408 * Failure: NTSTATUS code.
1410 * SEE ALSO
1411 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1414 NTSTATUS WINAPI
1415 RtlAdjustPrivilege(ULONG Privilege,
1416 BOOLEAN Enable,
1417 BOOLEAN CurrentThread,
1418 PBOOLEAN Enabled)
1420 TOKEN_PRIVILEGES NewState;
1421 TOKEN_PRIVILEGES OldState;
1422 ULONG ReturnLength;
1423 HANDLE TokenHandle;
1424 NTSTATUS Status;
1426 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1427 CurrentThread ? "TRUE" : "FALSE", Enabled);
1429 if (CurrentThread)
1431 Status = NtOpenThreadToken(GetCurrentThread(),
1432 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1433 FALSE,
1434 &TokenHandle);
1436 else
1438 Status = NtOpenProcessToken(GetCurrentProcess(),
1439 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1440 &TokenHandle);
1443 if (!NT_SUCCESS(Status))
1445 WARN("Retrieving token handle failed (Status %x)\n", Status);
1446 return Status;
1449 OldState.PrivilegeCount = 1;
1451 NewState.PrivilegeCount = 1;
1452 NewState.Privileges[0].Luid.LowPart = Privilege;
1453 NewState.Privileges[0].Luid.HighPart = 0;
1454 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1456 Status = NtAdjustPrivilegesToken(TokenHandle,
1457 FALSE,
1458 &NewState,
1459 sizeof(TOKEN_PRIVILEGES),
1460 &OldState,
1461 &ReturnLength);
1462 NtClose (TokenHandle);
1463 if (Status == STATUS_NOT_ALL_ASSIGNED)
1465 TRACE("Failed to assign all privileges\n");
1466 return STATUS_PRIVILEGE_NOT_HELD;
1468 if (!NT_SUCCESS(Status))
1470 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1471 return Status;
1474 if (OldState.PrivilegeCount == 0)
1475 *Enabled = Enable;
1476 else
1477 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1479 return STATUS_SUCCESS;
1482 /******************************************************************************
1483 * RtlImpersonateSelf [NTDLL.@]
1485 * Makes an impersonation token that represents the process user and assigns
1486 * to the current thread.
1488 * PARAMS
1489 * ImpersonationLevel [I] Level at which to impersonate.
1491 * RETURNS
1492 * Success: STATUS_SUCCESS.
1493 * Failure: NTSTATUS code.
1495 NTSTATUS WINAPI
1496 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1498 NTSTATUS Status;
1499 OBJECT_ATTRIBUTES ObjectAttributes;
1500 HANDLE ProcessToken;
1501 HANDLE ImpersonationToken;
1503 TRACE("(%08x)\n", ImpersonationLevel);
1505 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1506 &ProcessToken);
1507 if (Status != STATUS_SUCCESS)
1508 return Status;
1510 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1512 Status = NtDuplicateToken( ProcessToken,
1513 TOKEN_IMPERSONATE,
1514 &ObjectAttributes,
1515 ImpersonationLevel,
1516 TokenImpersonation,
1517 &ImpersonationToken );
1518 if (Status != STATUS_SUCCESS)
1520 NtClose( ProcessToken );
1521 return Status;
1524 Status = NtSetInformationThread( GetCurrentThread(),
1525 ThreadImpersonationToken,
1526 &ImpersonationToken,
1527 sizeof(ImpersonationToken) );
1529 NtClose( ImpersonationToken );
1530 NtClose( ProcessToken );
1532 return Status;
1535 /******************************************************************************
1536 * NtImpersonateAnonymousToken [NTDLL.@]
1538 NTSTATUS WINAPI
1539 NtImpersonateAnonymousToken(HANDLE thread)
1541 FIXME("(%p): stub\n", thread);
1542 return STATUS_NOT_IMPLEMENTED;
1545 /******************************************************************************
1546 * NtAccessCheck [NTDLL.@]
1547 * ZwAccessCheck [NTDLL.@]
1549 * Checks that a user represented by a token is allowed to access an object
1550 * represented by a security descriptor.
1552 * PARAMS
1553 * SecurityDescriptor [I] The security descriptor of the object to check.
1554 * ClientToken [I] Token of the user accessing the object.
1555 * DesiredAccess [I] The desired access to the object.
1556 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1557 * PrivilegeSet [I/O] Privileges used during the access check.
1558 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1559 * GrantedAccess [O] The actual access rights granted.
1560 * AccessStatus [O] The status of the access check.
1562 * RETURNS
1563 * NTSTATUS code.
1565 * NOTES
1566 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1567 * the maximum access rights allowed by the SD and returns them in
1568 * GrantedAccess.
1569 * The SecurityDescriptor must have a valid owner and groups present,
1570 * otherwise the function will fail.
1572 NTSTATUS WINAPI
1573 NtAccessCheck(
1574 PSECURITY_DESCRIPTOR SecurityDescriptor,
1575 HANDLE ClientToken,
1576 ACCESS_MASK DesiredAccess,
1577 PGENERIC_MAPPING GenericMapping,
1578 PPRIVILEGE_SET PrivilegeSet,
1579 PULONG ReturnLength,
1580 PULONG GrantedAccess,
1581 NTSTATUS *AccessStatus)
1583 NTSTATUS status;
1585 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1586 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1587 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1589 if (!PrivilegeSet || !ReturnLength)
1590 return STATUS_ACCESS_VIOLATION;
1592 SERVER_START_REQ( access_check )
1594 struct security_descriptor sd;
1595 PSID owner;
1596 PSID group;
1597 PACL sacl;
1598 PACL dacl;
1599 BOOLEAN defaulted, present;
1600 DWORD revision;
1601 SECURITY_DESCRIPTOR_CONTROL control;
1603 req->handle = wine_server_obj_handle( ClientToken );
1604 req->desired_access = DesiredAccess;
1605 req->mapping_read = GenericMapping->GenericRead;
1606 req->mapping_write = GenericMapping->GenericWrite;
1607 req->mapping_execute = GenericMapping->GenericExecute;
1608 req->mapping_all = GenericMapping->GenericAll;
1610 /* marshal security descriptor */
1611 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1612 sd.control = control & ~SE_SELF_RELATIVE;
1613 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1614 sd.owner_len = RtlLengthSid( owner );
1615 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1616 sd.group_len = RtlLengthSid( group );
1617 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1618 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1619 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1620 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1622 wine_server_add_data( req, &sd, sizeof(sd) );
1623 wine_server_add_data( req, owner, sd.owner_len );
1624 wine_server_add_data( req, group, sd.group_len );
1625 wine_server_add_data( req, sacl, sd.sacl_len );
1626 wine_server_add_data( req, dacl, sd.dacl_len );
1628 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1630 status = wine_server_call( req );
1632 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1633 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1635 if (status == STATUS_SUCCESS)
1637 *AccessStatus = reply->access_status;
1638 *GrantedAccess = reply->access_granted;
1641 SERVER_END_REQ;
1643 return status;
1646 /******************************************************************************
1647 * NtSetSecurityObject [NTDLL.@]
1648 * ZwSetSecurityObject [NTDLL.@]
1650 * Sets specified parts of the object's security descriptor.
1652 * PARAMS
1653 * Handle [I] Handle to the object to change security descriptor of.
1654 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1655 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1657 * RETURNS
1658 * NTSTATUS code.
1661 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1662 SECURITY_INFORMATION SecurityInformation,
1663 PSECURITY_DESCRIPTOR SecurityDescriptor)
1665 NTSTATUS status;
1666 struct security_descriptor sd;
1667 PACL dacl = NULL, sacl = NULL;
1668 PSID owner = NULL, group = NULL;
1669 BOOLEAN defaulted, present;
1670 DWORD revision;
1671 SECURITY_DESCRIPTOR_CONTROL control;
1673 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1675 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1677 memset( &sd, 0, sizeof(sd) );
1678 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1679 if (status != STATUS_SUCCESS) return status;
1680 sd.control = control & ~SE_SELF_RELATIVE;
1682 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1684 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1685 if (status != STATUS_SUCCESS) return status;
1686 if (!(sd.owner_len = RtlLengthSid( owner )))
1687 return STATUS_INVALID_SECURITY_DESCR;
1690 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1692 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1693 if (status != STATUS_SUCCESS) return status;
1694 if (!(sd.group_len = RtlLengthSid( group )))
1695 return STATUS_INVALID_SECURITY_DESCR;
1698 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1700 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1701 if (status != STATUS_SUCCESS) return status;
1702 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1703 sd.control |= SE_SACL_PRESENT;
1706 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1708 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1709 if (status != STATUS_SUCCESS) return status;
1710 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1711 sd.control |= SE_DACL_PRESENT;
1714 SERVER_START_REQ( set_security_object )
1716 req->handle = wine_server_obj_handle( Handle );
1717 req->security_info = SecurityInformation;
1719 wine_server_add_data( req, &sd, sizeof(sd) );
1720 wine_server_add_data( req, owner, sd.owner_len );
1721 wine_server_add_data( req, group, sd.group_len );
1722 wine_server_add_data( req, sacl, sd.sacl_len );
1723 wine_server_add_data( req, dacl, sd.dacl_len );
1724 status = wine_server_call( req );
1726 SERVER_END_REQ;
1728 return status;
1731 /******************************************************************************
1732 * RtlConvertSidToUnicodeString (NTDLL.@)
1734 * The returned SID is used to access the USER registry hive usually
1736 * the native function returns something like
1737 * "S-1-5-21-0000000000-000000000-0000000000-500";
1739 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1740 PUNICODE_STRING String,
1741 PSID pSid,
1742 BOOLEAN AllocateString)
1744 static const WCHAR formatW[] = {'-','%','u',0};
1745 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1746 WCHAR *p = buffer;
1747 const SID *sid = pSid;
1748 DWORD i, len;
1750 *p++ = 'S';
1751 p += sprintfW( p, formatW, sid->Revision );
1752 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1753 sid->IdentifierAuthority.Value[4] ),
1754 MAKEWORD( sid->IdentifierAuthority.Value[3],
1755 sid->IdentifierAuthority.Value[2] )));
1756 for (i = 0; i < sid->SubAuthorityCount; i++)
1757 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1759 len = (p + 1 - buffer) * sizeof(WCHAR);
1761 String->Length = len - sizeof(WCHAR);
1762 if (AllocateString)
1764 String->MaximumLength = len;
1765 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1766 return STATUS_NO_MEMORY;
1768 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1770 memcpy( String->Buffer, buffer, len );
1771 return STATUS_SUCCESS;
1774 /******************************************************************************
1775 * RtlQueryInformationAcl (NTDLL.@)
1777 NTSTATUS WINAPI RtlQueryInformationAcl(
1778 PACL pAcl,
1779 LPVOID pAclInformation,
1780 DWORD nAclInformationLength,
1781 ACL_INFORMATION_CLASS dwAclInformationClass)
1783 NTSTATUS status = STATUS_SUCCESS;
1785 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1786 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1788 switch (dwAclInformationClass)
1790 case AclRevisionInformation:
1792 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1794 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1795 status = STATUS_INVALID_PARAMETER;
1796 else
1797 paclrev->AclRevision = pAcl->AclRevision;
1799 break;
1802 case AclSizeInformation:
1804 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1806 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1807 status = STATUS_INVALID_PARAMETER;
1808 else
1810 paclsize->AceCount = pAcl->AceCount;
1811 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1812 if (pAcl->AclSize < paclsize->AclBytesInUse)
1814 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1815 paclsize->AclBytesFree = 0;
1816 paclsize->AclBytesInUse = pAcl->AclSize;
1818 else
1819 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1822 break;
1825 default:
1826 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1827 status = STATUS_INVALID_PARAMETER;
1830 return status;
1833 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1834 PSECURITY_DESCRIPTOR pdesc,
1835 PSECURITY_DESCRIPTOR cdesc,
1836 PSECURITY_DESCRIPTOR* ndesc,
1837 GUID* objtype,
1838 BOOL isdir,
1839 PGENERIC_MAPPING genmap )
1841 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1843 return FALSE;