mshtml/tests: Added more ownerDocument property tests.
[wine.git] / dlls / ntdll / sec.c
blob02fc77dc1cc1e27f16a893a737481b2f008cf920
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 (!(pAbs->Control & SE_SELF_RELATIVE)) length -= (sizeof(*pAbs) - sizeof(*pRel));
864 if (*lpdwBufferLength < length)
866 *lpdwBufferLength = length;
867 return STATUS_BUFFER_TOO_SMALL;
870 if (!pRel)
871 return STATUS_INVALID_PARAMETER;
873 if (pAbs->Control & SE_SELF_RELATIVE)
875 memcpy(pRel, pAbs, length);
876 return STATUS_SUCCESS;
879 pRel->Revision = pAbs->Revision;
880 pRel->Sbz1 = pAbs->Sbz1;
881 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
883 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
884 if (pAbs->Owner)
886 pRel->Owner = offsetRel;
887 length = RtlLengthSid(pAbs->Owner);
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
889 offsetRel += length;
891 else
893 pRel->Owner = 0;
896 if (pAbs->Group)
898 pRel->Group = offsetRel;
899 length = RtlLengthSid(pAbs->Group);
900 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
901 offsetRel += length;
903 else
905 pRel->Group = 0;
908 if (pAbs->Sacl)
910 pRel->Sacl = offsetRel;
911 length = pAbs->Sacl->AclSize;
912 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
913 offsetRel += length;
915 else
917 pRel->Sacl = 0;
920 if (pAbs->Dacl)
922 pRel->Dacl = offsetRel;
923 length = pAbs->Dacl->AclSize;
924 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
926 else
928 pRel->Dacl = 0;
931 return STATUS_SUCCESS;
935 /**************************************************************************
936 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
938 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
939 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
940 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
941 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
942 OUT PACL pDacl,
943 OUT LPDWORD lpdwDaclSize,
944 OUT PACL pSacl,
945 OUT LPDWORD lpdwSaclSize,
946 OUT PSID pOwner,
947 OUT LPDWORD lpdwOwnerSize,
948 OUT PSID pPrimaryGroup,
949 OUT LPDWORD lpdwPrimaryGroupSize)
951 NTSTATUS status = STATUS_SUCCESS;
952 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
953 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
955 if (!pRel ||
956 !lpdwAbsoluteSecurityDescriptorSize ||
957 !lpdwDaclSize ||
958 !lpdwSaclSize ||
959 !lpdwOwnerSize ||
960 !lpdwPrimaryGroupSize ||
961 ~pRel->Control & SE_SELF_RELATIVE)
962 return STATUS_INVALID_PARAMETER;
964 /* Confirm buffers are sufficiently large */
965 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
967 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
968 status = STATUS_BUFFER_TOO_SMALL;
971 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
972 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
974 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
975 status = STATUS_BUFFER_TOO_SMALL;
978 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
979 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
981 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
982 status = STATUS_BUFFER_TOO_SMALL;
985 if (pRel->Owner &&
986 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
988 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
989 status = STATUS_BUFFER_TOO_SMALL;
992 if (pRel->Group &&
993 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
995 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
996 status = STATUS_BUFFER_TOO_SMALL;
999 if (status != STATUS_SUCCESS)
1000 return status;
1002 /* Copy structures, and clear the ones we don't set */
1003 pAbs->Revision = pRel->Revision;
1004 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
1005 pAbs->Sacl = NULL;
1006 pAbs->Dacl = NULL;
1007 pAbs->Owner = NULL;
1008 pAbs->Group = NULL;
1010 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1012 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1014 memcpy(pSacl, pAcl, pAcl->AclSize);
1015 pAbs->Sacl = pSacl;
1018 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1020 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1021 memcpy(pDacl, pAcl, pAcl->AclSize);
1022 pAbs->Dacl = pDacl;
1025 if (pRel->Owner)
1027 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1028 memcpy(pOwner, psid, RtlLengthSid(psid));
1029 pAbs->Owner = pOwner;
1032 if (pRel->Group)
1034 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1035 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1036 pAbs->Group = pPrimaryGroup;
1039 return status;
1042 /******************************************************************************
1043 * RtlGetControlSecurityDescriptor (NTDLL.@)
1045 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1046 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1047 PSECURITY_DESCRIPTOR_CONTROL pControl,
1048 LPDWORD lpdwRevision)
1050 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1052 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1054 *lpdwRevision = lpsd->Revision;
1056 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1057 return STATUS_UNKNOWN_REVISION;
1059 *pControl = lpsd->Control;
1061 return STATUS_SUCCESS;
1064 /******************************************************************************
1065 * RtlSetControlSecurityDescriptor (NTDLL.@)
1067 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1068 PSECURITY_DESCRIPTOR SecurityDescriptor,
1069 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1070 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1072 SECURITY_DESCRIPTOR_CONTROL const immutable
1073 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1074 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1075 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1076 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1079 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1081 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1082 ControlBitsOfInterest, ControlBitsToSet);
1084 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1085 return STATUS_INVALID_PARAMETER;
1087 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1088 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1090 return STATUS_SUCCESS;
1094 /**************************************************************************
1095 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1097 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1098 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1099 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1100 PULONG BufferLength)
1102 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1104 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1105 SelfRelativeSecurityDescriptor, BufferLength);
1107 if (abs->Control & SE_SELF_RELATIVE)
1108 return STATUS_BAD_DESCRIPTOR_FORMAT;
1110 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1111 SelfRelativeSecurityDescriptor, BufferLength);
1116 * access control list's
1119 /**************************************************************************
1120 * RtlCreateAcl [NTDLL.@]
1122 * NOTES
1123 * This should return NTSTATUS
1125 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1127 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1129 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1130 return STATUS_INVALID_PARAMETER;
1131 if (size<sizeof(ACL))
1132 return STATUS_BUFFER_TOO_SMALL;
1133 if (size>0xFFFF)
1134 return STATUS_INVALID_PARAMETER;
1136 memset(acl,'\0',sizeof(ACL));
1137 acl->AclRevision = rev;
1138 acl->AclSize = size;
1139 acl->AceCount = 0;
1140 return STATUS_SUCCESS;
1143 /**************************************************************************
1144 * RtlFirstFreeAce [NTDLL.@]
1145 * looks for the AceCount+1 ACE, and if it is still within the alloced
1146 * ACL, return a pointer to it
1148 BOOLEAN WINAPI RtlFirstFreeAce(
1149 PACL acl,
1150 PACE_HEADER *x)
1152 PACE_HEADER ace;
1153 int i;
1155 *x = 0;
1156 ace = (PACE_HEADER)(acl+1);
1157 for (i=0;i<acl->AceCount;i++) {
1158 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1159 return FALSE;
1160 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1162 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1163 return FALSE;
1164 *x = ace;
1165 return TRUE;
1168 /**************************************************************************
1169 * RtlAddAce [NTDLL.@]
1171 NTSTATUS WINAPI RtlAddAce(
1172 PACL acl,
1173 DWORD rev,
1174 DWORD xnrofaces,
1175 PACE_HEADER acestart,
1176 DWORD acelen)
1178 PACE_HEADER ace,targetace;
1179 int nrofaces;
1181 if (!RtlValidAcl(acl))
1182 return STATUS_INVALID_PARAMETER;
1183 if (!RtlFirstFreeAce(acl,&targetace))
1184 return STATUS_INVALID_PARAMETER;
1185 nrofaces=0;ace=acestart;
1186 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1187 nrofaces++;
1188 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1190 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1191 return STATUS_INVALID_PARAMETER;
1192 memcpy(targetace,acestart,acelen);
1193 acl->AceCount+=nrofaces;
1194 if (rev > acl->AclRevision)
1195 acl->AclRevision = rev;
1196 return STATUS_SUCCESS;
1199 /**************************************************************************
1200 * RtlDeleteAce [NTDLL.@]
1202 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1204 NTSTATUS status;
1205 PACE_HEADER pAce;
1207 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1209 if (STATUS_SUCCESS == status)
1211 PACE_HEADER pcAce;
1212 DWORD len = 0;
1214 /* skip over the ACE we are deleting */
1215 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1216 dwAceIndex++;
1218 /* calculate the length of the rest */
1219 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1221 len += pcAce->AceSize;
1222 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1225 /* slide them all backwards */
1226 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1227 pAcl->AceCount--;
1230 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1232 return status;
1235 /******************************************************************************
1236 * RtlAddAccessAllowedAce [NTDLL.@]
1238 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1239 IN OUT PACL pAcl,
1240 IN DWORD dwAceRevision,
1241 IN DWORD AccessMask,
1242 IN PSID pSid)
1244 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1247 /******************************************************************************
1248 * RtlAddAccessAllowedAceEx [NTDLL.@]
1250 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1251 IN OUT PACL pAcl,
1252 IN DWORD dwAceRevision,
1253 IN DWORD AceFlags,
1254 IN DWORD AccessMask,
1255 IN PSID pSid)
1257 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1259 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1260 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1263 /******************************************************************************
1264 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1266 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1267 IN OUT PACL pAcl,
1268 IN DWORD dwAceRevision,
1269 IN DWORD dwAceFlags,
1270 IN DWORD dwAccessMask,
1271 IN GUID* pObjectTypeGuid,
1272 IN GUID* pInheritedObjectTypeGuid,
1273 IN PSID pSid)
1275 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1276 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1277 return STATUS_NOT_IMPLEMENTED;
1280 /******************************************************************************
1281 * RtlAddAccessDeniedAce [NTDLL.@]
1283 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1284 IN OUT PACL pAcl,
1285 IN DWORD dwAceRevision,
1286 IN DWORD AccessMask,
1287 IN PSID pSid)
1289 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1292 /******************************************************************************
1293 * RtlAddAccessDeniedAceEx [NTDLL.@]
1295 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1296 IN OUT PACL pAcl,
1297 IN DWORD dwAceRevision,
1298 IN DWORD AceFlags,
1299 IN DWORD AccessMask,
1300 IN PSID pSid)
1302 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1304 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1305 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1308 /******************************************************************************
1309 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1311 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1312 IN OUT PACL pAcl,
1313 IN DWORD dwAceRevision,
1314 IN DWORD dwAceFlags,
1315 IN DWORD dwAccessMask,
1316 IN GUID* pObjectTypeGuid,
1317 IN GUID* pInheritedObjectTypeGuid,
1318 IN PSID pSid)
1320 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1321 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1322 return STATUS_NOT_IMPLEMENTED;
1325 /**************************************************************************
1326 * RtlAddAuditAccessAce [NTDLL.@]
1328 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1329 IN OUT PACL pAcl,
1330 IN DWORD dwAceRevision,
1331 IN DWORD dwAceFlags,
1332 IN DWORD dwAccessMask,
1333 IN PSID pSid,
1334 IN BOOL bAuditSuccess,
1335 IN BOOL bAuditFailure)
1337 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1338 pSid,bAuditSuccess,bAuditFailure);
1340 if (bAuditSuccess)
1341 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1343 if (bAuditFailure)
1344 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1346 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1347 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1350 /**************************************************************************
1351 * RtlAddAuditAccessAce [NTDLL.@]
1353 NTSTATUS WINAPI RtlAddAuditAccessAce(
1354 IN OUT PACL pAcl,
1355 IN DWORD dwAceRevision,
1356 IN DWORD dwAccessMask,
1357 IN PSID pSid,
1358 IN BOOL bAuditSuccess,
1359 IN BOOL bAuditFailure)
1361 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1364 /******************************************************************************
1365 * RtlAddAuditAccessObjectAce [NTDLL.@]
1367 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1368 IN OUT PACL pAcl,
1369 IN DWORD dwAceRevision,
1370 IN DWORD dwAceFlags,
1371 IN DWORD dwAccessMask,
1372 IN GUID* pObjectTypeGuid,
1373 IN GUID* pInheritedObjectTypeGuid,
1374 IN PSID pSid,
1375 IN BOOL bAuditSuccess,
1376 IN BOOL bAuditFailure)
1378 FIXME("%p %x %x %x %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1379 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1380 return STATUS_NOT_IMPLEMENTED;
1383 /**************************************************************************
1384 * RtlAddMandatoryAce [NTDLL.@]
1386 NTSTATUS WINAPI RtlAddMandatoryAce(
1387 IN OUT PACL pAcl,
1388 IN DWORD dwAceRevision,
1389 IN DWORD dwAceFlags,
1390 IN DWORD dwMandatoryFlags,
1391 IN DWORD dwAceType,
1392 IN PSID pSid)
1394 static const DWORD valid_flags = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP |
1395 SYSTEM_MANDATORY_LABEL_NO_READ_UP |
1396 SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP;
1398 TRACE("(%p, %u, 0x%08x, 0x%08x, %u, %p)\n", pAcl, dwAceRevision, dwAceFlags,
1399 dwMandatoryFlags, dwAceType, pSid);
1401 if (dwAceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
1402 return STATUS_INVALID_PARAMETER;
1404 if (dwMandatoryFlags & ~valid_flags)
1405 return STATUS_INVALID_PARAMETER;
1407 return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, pSid, dwAceType);
1410 /******************************************************************************
1411 * RtlValidAcl [NTDLL.@]
1413 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1415 BOOLEAN ret;
1416 TRACE("(%p)\n", pAcl);
1418 __TRY
1420 PACE_HEADER ace;
1421 int i;
1423 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1424 pAcl->AclRevision > MAX_ACL_REVISION)
1425 ret = FALSE;
1426 else
1428 ace = (PACE_HEADER)(pAcl+1);
1429 ret = TRUE;
1430 for (i=0;i<=pAcl->AceCount;i++)
1432 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1434 ret = FALSE;
1435 break;
1437 if (i != pAcl->AceCount)
1438 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1442 __EXCEPT_PAGE_FAULT
1444 WARN("(%p): invalid pointer!\n", pAcl);
1445 return FALSE;
1447 __ENDTRY
1448 return ret;
1451 /******************************************************************************
1452 * RtlGetAce [NTDLL.@]
1454 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1456 PACE_HEADER ace;
1458 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1460 if (dwAceIndex >= pAcl->AceCount)
1461 return STATUS_INVALID_PARAMETER;
1463 ace = (PACE_HEADER)(pAcl + 1);
1464 for (;dwAceIndex;dwAceIndex--)
1465 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1467 *pAce = ace;
1469 return STATUS_SUCCESS;
1473 * misc
1476 /******************************************************************************
1477 * RtlAdjustPrivilege [NTDLL.@]
1479 * Enables or disables a privilege from the calling thread or process.
1481 * PARAMS
1482 * Privilege [I] Privilege index to change.
1483 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1484 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1485 * Enabled [O] Whether privilege was previously enabled or disabled.
1487 * RETURNS
1488 * Success: STATUS_SUCCESS.
1489 * Failure: NTSTATUS code.
1491 * SEE ALSO
1492 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1495 NTSTATUS WINAPI
1496 RtlAdjustPrivilege(ULONG Privilege,
1497 BOOLEAN Enable,
1498 BOOLEAN CurrentThread,
1499 PBOOLEAN Enabled)
1501 TOKEN_PRIVILEGES NewState;
1502 TOKEN_PRIVILEGES OldState;
1503 ULONG ReturnLength;
1504 HANDLE TokenHandle;
1505 NTSTATUS Status;
1507 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1508 CurrentThread ? "TRUE" : "FALSE", Enabled);
1510 if (CurrentThread)
1512 Status = NtOpenThreadToken(GetCurrentThread(),
1513 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1514 FALSE,
1515 &TokenHandle);
1517 else
1519 Status = NtOpenProcessToken(GetCurrentProcess(),
1520 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1521 &TokenHandle);
1524 if (!NT_SUCCESS(Status))
1526 WARN("Retrieving token handle failed (Status %x)\n", Status);
1527 return Status;
1530 OldState.PrivilegeCount = 1;
1532 NewState.PrivilegeCount = 1;
1533 NewState.Privileges[0].Luid.LowPart = Privilege;
1534 NewState.Privileges[0].Luid.HighPart = 0;
1535 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1537 Status = NtAdjustPrivilegesToken(TokenHandle,
1538 FALSE,
1539 &NewState,
1540 sizeof(TOKEN_PRIVILEGES),
1541 &OldState,
1542 &ReturnLength);
1543 NtClose (TokenHandle);
1544 if (Status == STATUS_NOT_ALL_ASSIGNED)
1546 TRACE("Failed to assign all privileges\n");
1547 return STATUS_PRIVILEGE_NOT_HELD;
1549 if (!NT_SUCCESS(Status))
1551 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1552 return Status;
1555 if (OldState.PrivilegeCount == 0)
1556 *Enabled = Enable;
1557 else
1558 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1560 return STATUS_SUCCESS;
1563 /******************************************************************************
1564 * RtlImpersonateSelf [NTDLL.@]
1566 * Makes an impersonation token that represents the process user and assigns
1567 * to the current thread.
1569 * PARAMS
1570 * ImpersonationLevel [I] Level at which to impersonate.
1572 * RETURNS
1573 * Success: STATUS_SUCCESS.
1574 * Failure: NTSTATUS code.
1576 NTSTATUS WINAPI
1577 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1579 NTSTATUS Status;
1580 OBJECT_ATTRIBUTES ObjectAttributes;
1581 HANDLE ProcessToken;
1582 HANDLE ImpersonationToken;
1584 TRACE("(%08x)\n", ImpersonationLevel);
1586 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1587 &ProcessToken);
1588 if (Status != STATUS_SUCCESS)
1589 return Status;
1591 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1593 Status = NtDuplicateToken( ProcessToken,
1594 TOKEN_IMPERSONATE,
1595 &ObjectAttributes,
1596 ImpersonationLevel,
1597 TokenImpersonation,
1598 &ImpersonationToken );
1599 if (Status != STATUS_SUCCESS)
1601 NtClose( ProcessToken );
1602 return Status;
1605 Status = NtSetInformationThread( GetCurrentThread(),
1606 ThreadImpersonationToken,
1607 &ImpersonationToken,
1608 sizeof(ImpersonationToken) );
1610 NtClose( ImpersonationToken );
1611 NtClose( ProcessToken );
1613 return Status;
1616 /******************************************************************************
1617 * NtImpersonateAnonymousToken [NTDLL.@]
1619 NTSTATUS WINAPI
1620 NtImpersonateAnonymousToken(HANDLE thread)
1622 FIXME("(%p): stub\n", thread);
1623 return STATUS_NOT_IMPLEMENTED;
1626 /******************************************************************************
1627 * NtAccessCheck [NTDLL.@]
1628 * ZwAccessCheck [NTDLL.@]
1630 * Checks that a user represented by a token is allowed to access an object
1631 * represented by a security descriptor.
1633 * PARAMS
1634 * SecurityDescriptor [I] The security descriptor of the object to check.
1635 * ClientToken [I] Token of the user accessing the object.
1636 * DesiredAccess [I] The desired access to the object.
1637 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1638 * PrivilegeSet [I/O] Privileges used during the access check.
1639 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1640 * GrantedAccess [O] The actual access rights granted.
1641 * AccessStatus [O] The status of the access check.
1643 * RETURNS
1644 * NTSTATUS code.
1646 * NOTES
1647 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1648 * the maximum access rights allowed by the SD and returns them in
1649 * GrantedAccess.
1650 * The SecurityDescriptor must have a valid owner and groups present,
1651 * otherwise the function will fail.
1653 NTSTATUS WINAPI
1654 NtAccessCheck(
1655 PSECURITY_DESCRIPTOR SecurityDescriptor,
1656 HANDLE ClientToken,
1657 ACCESS_MASK DesiredAccess,
1658 PGENERIC_MAPPING GenericMapping,
1659 PPRIVILEGE_SET PrivilegeSet,
1660 PULONG ReturnLength,
1661 PULONG GrantedAccess,
1662 NTSTATUS *AccessStatus)
1664 NTSTATUS status;
1666 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1667 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1668 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1670 if (!PrivilegeSet || !ReturnLength)
1671 return STATUS_ACCESS_VIOLATION;
1673 SERVER_START_REQ( access_check )
1675 struct security_descriptor sd;
1676 PSID owner;
1677 PSID group;
1678 PACL sacl;
1679 PACL dacl;
1680 BOOLEAN defaulted, present;
1681 DWORD revision;
1682 SECURITY_DESCRIPTOR_CONTROL control;
1684 req->handle = wine_server_obj_handle( ClientToken );
1685 req->desired_access = DesiredAccess;
1686 req->mapping_read = GenericMapping->GenericRead;
1687 req->mapping_write = GenericMapping->GenericWrite;
1688 req->mapping_execute = GenericMapping->GenericExecute;
1689 req->mapping_all = GenericMapping->GenericAll;
1691 /* marshal security descriptor */
1692 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1693 sd.control = control & ~SE_SELF_RELATIVE;
1694 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1695 sd.owner_len = RtlLengthSid( owner );
1696 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1697 sd.group_len = RtlLengthSid( group );
1698 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1699 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1700 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1701 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1703 wine_server_add_data( req, &sd, sizeof(sd) );
1704 wine_server_add_data( req, owner, sd.owner_len );
1705 wine_server_add_data( req, group, sd.group_len );
1706 wine_server_add_data( req, sacl, sd.sacl_len );
1707 wine_server_add_data( req, dacl, sd.dacl_len );
1709 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1711 status = wine_server_call( req );
1713 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1714 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1716 if (status == STATUS_SUCCESS)
1718 *AccessStatus = reply->access_status;
1719 *GrantedAccess = reply->access_granted;
1722 SERVER_END_REQ;
1724 return status;
1727 /******************************************************************************
1728 * NtSetSecurityObject [NTDLL.@]
1729 * ZwSetSecurityObject [NTDLL.@]
1731 * Sets specified parts of the object's security descriptor.
1733 * PARAMS
1734 * Handle [I] Handle to the object to change security descriptor of.
1735 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1736 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1738 * RETURNS
1739 * NTSTATUS code.
1742 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1743 SECURITY_INFORMATION SecurityInformation,
1744 PSECURITY_DESCRIPTOR SecurityDescriptor)
1746 NTSTATUS status;
1747 struct security_descriptor sd;
1748 PACL dacl = NULL, sacl = NULL;
1749 PSID owner = NULL, group = NULL;
1750 BOOLEAN defaulted, present;
1751 DWORD revision;
1752 SECURITY_DESCRIPTOR_CONTROL control;
1754 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1756 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1758 memset( &sd, 0, sizeof(sd) );
1759 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1760 if (status != STATUS_SUCCESS) return status;
1761 sd.control = control & ~SE_SELF_RELATIVE;
1763 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1765 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1766 if (status != STATUS_SUCCESS) return status;
1767 if (!(sd.owner_len = RtlLengthSid( owner )))
1768 return STATUS_INVALID_SECURITY_DESCR;
1771 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1773 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1774 if (status != STATUS_SUCCESS) return status;
1775 if (!(sd.group_len = RtlLengthSid( group )))
1776 return STATUS_INVALID_SECURITY_DESCR;
1779 if (SecurityInformation & SACL_SECURITY_INFORMATION ||
1780 SecurityInformation & LABEL_SECURITY_INFORMATION)
1782 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1783 if (status != STATUS_SUCCESS) return status;
1784 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1785 sd.control |= SE_SACL_PRESENT;
1788 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1790 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1791 if (status != STATUS_SUCCESS) return status;
1792 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1793 sd.control |= SE_DACL_PRESENT;
1796 SERVER_START_REQ( set_security_object )
1798 req->handle = wine_server_obj_handle( Handle );
1799 req->security_info = SecurityInformation;
1801 wine_server_add_data( req, &sd, sizeof(sd) );
1802 wine_server_add_data( req, owner, sd.owner_len );
1803 wine_server_add_data( req, group, sd.group_len );
1804 wine_server_add_data( req, sacl, sd.sacl_len );
1805 wine_server_add_data( req, dacl, sd.dacl_len );
1806 status = wine_server_call( req );
1808 SERVER_END_REQ;
1810 return status;
1813 /******************************************************************************
1814 * RtlConvertSidToUnicodeString (NTDLL.@)
1816 * The returned SID is used to access the USER registry hive usually
1818 * the native function returns something like
1819 * "S-1-5-21-0000000000-000000000-0000000000-500";
1821 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1822 PUNICODE_STRING String,
1823 PSID pSid,
1824 BOOLEAN AllocateString)
1826 static const WCHAR formatW[] = {'-','%','u',0};
1827 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1828 WCHAR *p = buffer;
1829 const SID *sid = pSid;
1830 DWORD i, len;
1832 *p++ = 'S';
1833 p += sprintfW( p, formatW, sid->Revision );
1834 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1835 sid->IdentifierAuthority.Value[4] ),
1836 MAKEWORD( sid->IdentifierAuthority.Value[3],
1837 sid->IdentifierAuthority.Value[2] )));
1838 for (i = 0; i < sid->SubAuthorityCount; i++)
1839 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1841 len = (p + 1 - buffer) * sizeof(WCHAR);
1843 String->Length = len - sizeof(WCHAR);
1844 if (AllocateString)
1846 String->MaximumLength = len;
1847 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1848 return STATUS_NO_MEMORY;
1850 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1852 memcpy( String->Buffer, buffer, len );
1853 return STATUS_SUCCESS;
1856 /******************************************************************************
1857 * RtlQueryInformationAcl (NTDLL.@)
1859 NTSTATUS WINAPI RtlQueryInformationAcl(
1860 PACL pAcl,
1861 LPVOID pAclInformation,
1862 DWORD nAclInformationLength,
1863 ACL_INFORMATION_CLASS dwAclInformationClass)
1865 NTSTATUS status = STATUS_SUCCESS;
1867 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1868 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1870 switch (dwAclInformationClass)
1872 case AclRevisionInformation:
1874 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1876 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1877 status = STATUS_INVALID_PARAMETER;
1878 else
1879 paclrev->AclRevision = pAcl->AclRevision;
1881 break;
1884 case AclSizeInformation:
1886 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1888 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1889 status = STATUS_INVALID_PARAMETER;
1890 else
1892 paclsize->AceCount = pAcl->AceCount;
1893 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1894 if (pAcl->AclSize < paclsize->AclBytesInUse)
1896 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1897 paclsize->AclBytesFree = 0;
1898 paclsize->AclBytesInUse = pAcl->AclSize;
1900 else
1901 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1904 break;
1907 default:
1908 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1909 status = STATUS_INVALID_PARAMETER;
1912 return status;
1915 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1916 PSECURITY_DESCRIPTOR pdesc,
1917 PSECURITY_DESCRIPTOR cdesc,
1918 PSECURITY_DESCRIPTOR* ndesc,
1919 GUID* objtype,
1920 BOOL isdir,
1921 PGENERIC_MAPPING genmap )
1923 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1925 return FALSE;