mscoree: Implement IMetahostPolicy GetRequestedRuntime.
[wine/wine-gecko.git] / dlls / ntdll / sec.c
blobb9eeccda616590a6904da83580dc4b802b4b27a6
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 * RtlLengthSecurityDescriptor [NTDLL.@]
563 ULONG WINAPI RtlLengthSecurityDescriptor(
564 PSECURITY_DESCRIPTOR pSecurityDescriptor)
566 ULONG size;
568 if ( pSecurityDescriptor == NULL )
569 return 0;
571 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
573 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
574 size = sizeof(*sd);
575 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
576 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
577 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
578 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
579 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
580 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
582 else
584 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
585 size = sizeof(*sd);
586 if (sd->Owner) size += RtlLengthSid( sd->Owner );
587 if (sd->Group) size += RtlLengthSid( sd->Group );
588 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
591 return size;
594 /******************************************************************************
595 * RtlGetDaclSecurityDescriptor [NTDLL.@]
598 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
599 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
600 OUT PBOOLEAN lpbDaclPresent,
601 OUT PACL *pDacl,
602 OUT PBOOLEAN lpbDaclDefaulted)
604 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606 TRACE("(%p,%p,%p,%p)\n",
607 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
610 return STATUS_UNKNOWN_REVISION ;
612 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614 if (lpsd->Control & SE_SELF_RELATIVE)
616 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
617 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
618 else *pDacl = NULL;
620 else *pDacl = lpsd->Dacl;
622 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
624 else
626 *pDacl = NULL;
627 *lpbDaclDefaulted = 0;
630 return STATUS_SUCCESS;
633 /**************************************************************************
634 * RtlSetDaclSecurityDescriptor [NTDLL.@]
636 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
637 PSECURITY_DESCRIPTOR pSecurityDescriptor,
638 BOOLEAN daclpresent,
639 PACL dacl,
640 BOOLEAN dacldefaulted )
642 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
644 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
645 return STATUS_UNKNOWN_REVISION;
646 if (lpsd->Control & SE_SELF_RELATIVE)
647 return STATUS_INVALID_SECURITY_DESCR;
649 if (!daclpresent)
651 lpsd->Control &= ~SE_DACL_PRESENT;
652 return STATUS_SUCCESS;
655 lpsd->Control |= SE_DACL_PRESENT;
656 lpsd->Dacl = dacl;
658 if (dacldefaulted)
659 lpsd->Control |= SE_DACL_DEFAULTED;
660 else
661 lpsd->Control &= ~SE_DACL_DEFAULTED;
663 return STATUS_SUCCESS;
666 /******************************************************************************
667 * RtlGetSaclSecurityDescriptor [NTDLL.@]
670 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
671 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
672 OUT PBOOLEAN lpbSaclPresent,
673 OUT PACL *pSacl,
674 OUT PBOOLEAN lpbSaclDefaulted)
676 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
678 TRACE("(%p,%p,%p,%p)\n",
679 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
681 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
682 return STATUS_UNKNOWN_REVISION;
684 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
686 if (lpsd->Control & SE_SELF_RELATIVE)
688 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
689 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
690 else *pSacl = NULL;
692 else *pSacl = lpsd->Sacl;
694 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
696 return STATUS_SUCCESS;
699 /**************************************************************************
700 * RtlSetSaclSecurityDescriptor [NTDLL.@]
702 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
703 PSECURITY_DESCRIPTOR pSecurityDescriptor,
704 BOOLEAN saclpresent,
705 PACL sacl,
706 BOOLEAN sacldefaulted)
708 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
710 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
711 return STATUS_UNKNOWN_REVISION;
712 if (lpsd->Control & SE_SELF_RELATIVE)
713 return STATUS_INVALID_SECURITY_DESCR;
714 if (!saclpresent) {
715 lpsd->Control &= ~SE_SACL_PRESENT;
716 return 0;
718 lpsd->Control |= SE_SACL_PRESENT;
719 lpsd->Sacl = sacl;
720 if (sacldefaulted)
721 lpsd->Control |= SE_SACL_DEFAULTED;
722 else
723 lpsd->Control &= ~SE_SACL_DEFAULTED;
724 return STATUS_SUCCESS;
727 /**************************************************************************
728 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
730 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
731 PSECURITY_DESCRIPTOR pSecurityDescriptor,
732 PSID *Owner,
733 PBOOLEAN OwnerDefaulted)
735 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
737 if ( !lpsd || !Owner || !OwnerDefaulted )
738 return STATUS_INVALID_PARAMETER;
740 if ( lpsd->Control & SE_OWNER_DEFAULTED )
741 *OwnerDefaulted = TRUE;
742 else
743 *OwnerDefaulted = FALSE;
745 if (lpsd->Control & SE_SELF_RELATIVE)
747 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
748 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
749 else *Owner = NULL;
751 else
752 *Owner = lpsd->Owner;
754 return STATUS_SUCCESS;
757 /**************************************************************************
758 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
760 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
761 PSECURITY_DESCRIPTOR pSecurityDescriptor,
762 PSID owner,
763 BOOLEAN ownerdefaulted)
765 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
767 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
768 return STATUS_UNKNOWN_REVISION;
769 if (lpsd->Control & SE_SELF_RELATIVE)
770 return STATUS_INVALID_SECURITY_DESCR;
772 lpsd->Owner = owner;
773 if (ownerdefaulted)
774 lpsd->Control |= SE_OWNER_DEFAULTED;
775 else
776 lpsd->Control &= ~SE_OWNER_DEFAULTED;
777 return STATUS_SUCCESS;
780 /**************************************************************************
781 * RtlSetGroupSecurityDescriptor [NTDLL.@]
783 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
784 PSECURITY_DESCRIPTOR pSecurityDescriptor,
785 PSID group,
786 BOOLEAN groupdefaulted)
788 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
790 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
791 return STATUS_UNKNOWN_REVISION;
792 if (lpsd->Control & SE_SELF_RELATIVE)
793 return STATUS_INVALID_SECURITY_DESCR;
795 lpsd->Group = group;
796 if (groupdefaulted)
797 lpsd->Control |= SE_GROUP_DEFAULTED;
798 else
799 lpsd->Control &= ~SE_GROUP_DEFAULTED;
800 return STATUS_SUCCESS;
803 /**************************************************************************
804 * RtlGetGroupSecurityDescriptor [NTDLL.@]
806 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
807 PSECURITY_DESCRIPTOR pSecurityDescriptor,
808 PSID *Group,
809 PBOOLEAN GroupDefaulted)
811 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
813 if ( !lpsd || !Group || !GroupDefaulted )
814 return STATUS_INVALID_PARAMETER;
816 if ( lpsd->Control & SE_GROUP_DEFAULTED )
817 *GroupDefaulted = TRUE;
818 else
819 *GroupDefaulted = FALSE;
821 if (lpsd->Control & SE_SELF_RELATIVE)
823 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
824 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
825 else *Group = NULL;
827 else
828 *Group = lpsd->Group;
830 return STATUS_SUCCESS;
833 /**************************************************************************
834 * RtlMakeSelfRelativeSD [NTDLL.@]
836 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
837 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
838 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
839 IN OUT LPDWORD lpdwBufferLength)
841 DWORD offsetRel;
842 ULONG length;
843 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
844 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
846 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
847 lpdwBufferLength ? *lpdwBufferLength: -1);
849 if (!lpdwBufferLength || !pAbs)
850 return STATUS_INVALID_PARAMETER;
852 length = RtlLengthSecurityDescriptor(pAbs);
853 if (*lpdwBufferLength < length)
855 *lpdwBufferLength = length;
856 return STATUS_BUFFER_TOO_SMALL;
859 if (!pRel)
860 return STATUS_INVALID_PARAMETER;
862 if (pAbs->Control & SE_SELF_RELATIVE)
864 memcpy(pRel, pAbs, length);
865 return STATUS_SUCCESS;
868 pRel->Revision = pAbs->Revision;
869 pRel->Sbz1 = pAbs->Sbz1;
870 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
872 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
873 if (pAbs->Owner)
875 pRel->Owner = offsetRel;
876 length = RtlLengthSid(pAbs->Owner);
877 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
878 offsetRel += length;
880 else
882 pRel->Owner = 0;
885 if (pAbs->Group)
887 pRel->Group = offsetRel;
888 length = RtlLengthSid(pAbs->Group);
889 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
890 offsetRel += length;
892 else
894 pRel->Group = 0;
897 if (pAbs->Sacl)
899 pRel->Sacl = offsetRel;
900 length = pAbs->Sacl->AclSize;
901 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
902 offsetRel += length;
904 else
906 pRel->Sacl = 0;
909 if (pAbs->Dacl)
911 pRel->Dacl = offsetRel;
912 length = pAbs->Dacl->AclSize;
913 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
915 else
917 pRel->Dacl = 0;
920 return STATUS_SUCCESS;
924 /**************************************************************************
925 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
927 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
928 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
929 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
930 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
931 OUT PACL pDacl,
932 OUT LPDWORD lpdwDaclSize,
933 OUT PACL pSacl,
934 OUT LPDWORD lpdwSaclSize,
935 OUT PSID pOwner,
936 OUT LPDWORD lpdwOwnerSize,
937 OUT PSID pPrimaryGroup,
938 OUT LPDWORD lpdwPrimaryGroupSize)
940 NTSTATUS status = STATUS_SUCCESS;
941 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
942 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
944 if (!pRel ||
945 !lpdwAbsoluteSecurityDescriptorSize ||
946 !lpdwDaclSize ||
947 !lpdwSaclSize ||
948 !lpdwOwnerSize ||
949 !lpdwPrimaryGroupSize ||
950 ~pRel->Control & SE_SELF_RELATIVE)
951 return STATUS_INVALID_PARAMETER;
953 /* Confirm buffers are sufficiently large */
954 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
956 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
957 status = STATUS_BUFFER_TOO_SMALL;
960 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
961 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
963 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
964 status = STATUS_BUFFER_TOO_SMALL;
967 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
968 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
970 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
971 status = STATUS_BUFFER_TOO_SMALL;
974 if (pRel->Owner &&
975 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
977 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
978 status = STATUS_BUFFER_TOO_SMALL;
981 if (pRel->Group &&
982 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
984 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
985 status = STATUS_BUFFER_TOO_SMALL;
988 if (status != STATUS_SUCCESS)
989 return status;
991 /* Copy structures, and clear the ones we don't set */
992 pAbs->Revision = pRel->Revision;
993 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
994 pAbs->Sacl = NULL;
995 pAbs->Dacl = NULL;
996 pAbs->Owner = NULL;
997 pAbs->Group = NULL;
999 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1001 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1003 memcpy(pSacl, pAcl, pAcl->AclSize);
1004 pAbs->Sacl = pSacl;
1007 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1009 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1010 memcpy(pDacl, pAcl, pAcl->AclSize);
1011 pAbs->Dacl = pDacl;
1014 if (pRel->Owner)
1016 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1017 memcpy(pOwner, psid, RtlLengthSid(psid));
1018 pAbs->Owner = pOwner;
1021 if (pRel->Group)
1023 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1024 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1025 pAbs->Group = pPrimaryGroup;
1028 return status;
1031 /******************************************************************************
1032 * RtlGetControlSecurityDescriptor (NTDLL.@)
1034 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1035 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1036 PSECURITY_DESCRIPTOR_CONTROL pControl,
1037 LPDWORD lpdwRevision)
1039 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1041 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1043 *lpdwRevision = lpsd->Revision;
1045 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1046 return STATUS_UNKNOWN_REVISION;
1048 *pControl = lpsd->Control;
1050 return STATUS_SUCCESS;
1053 /******************************************************************************
1054 * RtlSetControlSecurityDescriptor (NTDLL.@)
1056 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1057 PSECURITY_DESCRIPTOR SecurityDescriptor,
1058 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1059 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1061 SECURITY_DESCRIPTOR_CONTROL const immutable
1062 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1063 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1064 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1065 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1068 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1070 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1071 ControlBitsOfInterest, ControlBitsToSet);
1073 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1074 return STATUS_INVALID_PARAMETER;
1076 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1077 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1079 return STATUS_SUCCESS;
1083 /**************************************************************************
1084 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1086 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1087 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1088 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1089 PULONG BufferLength)
1091 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1093 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1094 SelfRelativeSecurityDescriptor, BufferLength);
1096 if (abs->Control & SE_SELF_RELATIVE)
1097 return STATUS_BAD_DESCRIPTOR_FORMAT;
1099 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1100 SelfRelativeSecurityDescriptor, BufferLength);
1105 * access control list's
1108 /**************************************************************************
1109 * RtlCreateAcl [NTDLL.@]
1111 * NOTES
1112 * This should return NTSTATUS
1114 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1116 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1118 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1119 return STATUS_INVALID_PARAMETER;
1120 if (size<sizeof(ACL))
1121 return STATUS_BUFFER_TOO_SMALL;
1122 if (size>0xFFFF)
1123 return STATUS_INVALID_PARAMETER;
1125 memset(acl,'\0',sizeof(ACL));
1126 acl->AclRevision = rev;
1127 acl->AclSize = size;
1128 acl->AceCount = 0;
1129 return STATUS_SUCCESS;
1132 /**************************************************************************
1133 * RtlFirstFreeAce [NTDLL.@]
1134 * looks for the AceCount+1 ACE, and if it is still within the alloced
1135 * ACL, return a pointer to it
1137 BOOLEAN WINAPI RtlFirstFreeAce(
1138 PACL acl,
1139 PACE_HEADER *x)
1141 PACE_HEADER ace;
1142 int i;
1144 *x = 0;
1145 ace = (PACE_HEADER)(acl+1);
1146 for (i=0;i<acl->AceCount;i++) {
1147 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1148 return 0;
1149 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1151 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1152 return 0;
1153 *x = ace;
1154 return 1;
1157 /**************************************************************************
1158 * RtlAddAce [NTDLL.@]
1160 NTSTATUS WINAPI RtlAddAce(
1161 PACL acl,
1162 DWORD rev,
1163 DWORD xnrofaces,
1164 PACE_HEADER acestart,
1165 DWORD acelen)
1167 PACE_HEADER ace,targetace;
1168 int nrofaces;
1170 if (acl->AclRevision != ACL_REVISION)
1171 return STATUS_INVALID_PARAMETER;
1172 if (!RtlFirstFreeAce(acl,&targetace))
1173 return STATUS_INVALID_PARAMETER;
1174 nrofaces=0;ace=acestart;
1175 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1176 nrofaces++;
1177 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1179 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1180 return STATUS_INVALID_PARAMETER;
1181 memcpy(targetace,acestart,acelen);
1182 acl->AceCount+=nrofaces;
1183 return STATUS_SUCCESS;
1186 /**************************************************************************
1187 * RtlDeleteAce [NTDLL.@]
1189 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1191 NTSTATUS status;
1192 PACE_HEADER pAce;
1194 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1196 if (STATUS_SUCCESS == status)
1198 PACE_HEADER pcAce;
1199 DWORD len = 0;
1201 /* skip over the ACE we are deleting */
1202 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1203 dwAceIndex++;
1205 /* calculate the length of the rest */
1206 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1208 len += pcAce->AceSize;
1209 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1212 /* slide them all backwards */
1213 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1214 pAcl->AceCount--;
1217 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1219 return status;
1222 /******************************************************************************
1223 * RtlAddAccessAllowedAce [NTDLL.@]
1225 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1226 IN OUT PACL pAcl,
1227 IN DWORD dwAceRevision,
1228 IN DWORD AccessMask,
1229 IN PSID pSid)
1231 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1234 /******************************************************************************
1235 * RtlAddAccessAllowedAceEx [NTDLL.@]
1237 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1238 IN OUT PACL pAcl,
1239 IN DWORD dwAceRevision,
1240 IN DWORD AceFlags,
1241 IN DWORD AccessMask,
1242 IN PSID pSid)
1244 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1246 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1247 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1250 /******************************************************************************
1251 * RtlAddAccessDeniedAce [NTDLL.@]
1253 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1254 IN OUT PACL pAcl,
1255 IN DWORD dwAceRevision,
1256 IN DWORD AccessMask,
1257 IN PSID pSid)
1259 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1262 /******************************************************************************
1263 * RtlAddAccessDeniedAceEx [NTDLL.@]
1265 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1266 IN OUT PACL pAcl,
1267 IN DWORD dwAceRevision,
1268 IN DWORD AceFlags,
1269 IN DWORD AccessMask,
1270 IN PSID pSid)
1272 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1274 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1275 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1278 /**************************************************************************
1279 * RtlAddAuditAccessAce [NTDLL.@]
1281 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1282 IN OUT PACL pAcl,
1283 IN DWORD dwAceRevision,
1284 IN DWORD dwAceFlags,
1285 IN DWORD dwAccessMask,
1286 IN PSID pSid,
1287 IN BOOL bAuditSuccess,
1288 IN BOOL bAuditFailure)
1290 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1291 pSid,bAuditSuccess,bAuditFailure);
1293 if (bAuditSuccess)
1294 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1296 if (bAuditFailure)
1297 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1299 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1300 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1303 /**************************************************************************
1304 * RtlAddAuditAccessAce [NTDLL.@]
1306 NTSTATUS WINAPI RtlAddAuditAccessAce(
1307 IN OUT PACL pAcl,
1308 IN DWORD dwAceRevision,
1309 IN DWORD dwAccessMask,
1310 IN PSID pSid,
1311 IN BOOL bAuditSuccess,
1312 IN BOOL bAuditFailure)
1314 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1317 /******************************************************************************
1318 * RtlValidAcl [NTDLL.@]
1320 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1322 BOOLEAN ret;
1323 TRACE("(%p)\n", pAcl);
1325 __TRY
1327 PACE_HEADER ace;
1328 int i;
1330 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1331 pAcl->AclRevision > MAX_ACL_REVISION)
1332 ret = FALSE;
1333 else
1335 ace = (PACE_HEADER)(pAcl+1);
1336 ret = TRUE;
1337 for (i=0;i<=pAcl->AceCount;i++)
1339 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1341 ret = FALSE;
1342 break;
1344 if (i != pAcl->AceCount)
1345 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1349 __EXCEPT_PAGE_FAULT
1351 WARN("(%p): invalid pointer!\n", pAcl);
1352 return 0;
1354 __ENDTRY
1355 return ret;
1358 /******************************************************************************
1359 * RtlGetAce [NTDLL.@]
1361 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1363 PACE_HEADER ace;
1365 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1367 if (dwAceIndex >= pAcl->AceCount)
1368 return STATUS_INVALID_PARAMETER;
1370 ace = (PACE_HEADER)(pAcl + 1);
1371 for (;dwAceIndex;dwAceIndex--)
1372 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1374 *pAce = ace;
1376 return STATUS_SUCCESS;
1380 * misc
1383 /******************************************************************************
1384 * RtlAdjustPrivilege [NTDLL.@]
1386 * Enables or disables a privilege from the calling thread or process.
1388 * PARAMS
1389 * Privilege [I] Privilege index to change.
1390 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1391 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1392 * Enabled [O] Whether privilege was previously enabled or disabled.
1394 * RETURNS
1395 * Success: STATUS_SUCCESS.
1396 * Failure: NTSTATUS code.
1398 * SEE ALSO
1399 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1402 NTSTATUS WINAPI
1403 RtlAdjustPrivilege(ULONG Privilege,
1404 BOOLEAN Enable,
1405 BOOLEAN CurrentThread,
1406 PBOOLEAN Enabled)
1408 TOKEN_PRIVILEGES NewState;
1409 TOKEN_PRIVILEGES OldState;
1410 ULONG ReturnLength;
1411 HANDLE TokenHandle;
1412 NTSTATUS Status;
1414 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1415 CurrentThread ? "TRUE" : "FALSE", Enabled);
1417 if (CurrentThread)
1419 Status = NtOpenThreadToken(GetCurrentThread(),
1420 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1421 FALSE,
1422 &TokenHandle);
1424 else
1426 Status = NtOpenProcessToken(GetCurrentProcess(),
1427 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1428 &TokenHandle);
1431 if (!NT_SUCCESS(Status))
1433 WARN("Retrieving token handle failed (Status %x)\n", Status);
1434 return Status;
1437 OldState.PrivilegeCount = 1;
1439 NewState.PrivilegeCount = 1;
1440 NewState.Privileges[0].Luid.LowPart = Privilege;
1441 NewState.Privileges[0].Luid.HighPart = 0;
1442 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1444 Status = NtAdjustPrivilegesToken(TokenHandle,
1445 FALSE,
1446 &NewState,
1447 sizeof(TOKEN_PRIVILEGES),
1448 &OldState,
1449 &ReturnLength);
1450 NtClose (TokenHandle);
1451 if (Status == STATUS_NOT_ALL_ASSIGNED)
1453 TRACE("Failed to assign all privileges\n");
1454 return STATUS_PRIVILEGE_NOT_HELD;
1456 if (!NT_SUCCESS(Status))
1458 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1459 return Status;
1462 if (OldState.PrivilegeCount == 0)
1463 *Enabled = Enable;
1464 else
1465 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1467 return STATUS_SUCCESS;
1470 /******************************************************************************
1471 * RtlImpersonateSelf [NTDLL.@]
1473 * Makes an impersonation token that represents the process user and assigns
1474 * to the current thread.
1476 * PARAMS
1477 * ImpersonationLevel [I] Level at which to impersonate.
1479 * RETURNS
1480 * Success: STATUS_SUCCESS.
1481 * Failure: NTSTATUS code.
1483 NTSTATUS WINAPI
1484 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1486 NTSTATUS Status;
1487 OBJECT_ATTRIBUTES ObjectAttributes;
1488 HANDLE ProcessToken;
1489 HANDLE ImpersonationToken;
1491 TRACE("(%08x)\n", ImpersonationLevel);
1493 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1494 &ProcessToken);
1495 if (Status != STATUS_SUCCESS)
1496 return Status;
1498 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1500 Status = NtDuplicateToken( ProcessToken,
1501 TOKEN_IMPERSONATE,
1502 &ObjectAttributes,
1503 ImpersonationLevel,
1504 TokenImpersonation,
1505 &ImpersonationToken );
1506 if (Status != STATUS_SUCCESS)
1508 NtClose( ProcessToken );
1509 return Status;
1512 Status = NtSetInformationThread( GetCurrentThread(),
1513 ThreadImpersonationToken,
1514 &ImpersonationToken,
1515 sizeof(ImpersonationToken) );
1517 NtClose( ImpersonationToken );
1518 NtClose( ProcessToken );
1520 return Status;
1523 /******************************************************************************
1524 * NtAccessCheck [NTDLL.@]
1525 * ZwAccessCheck [NTDLL.@]
1527 * Checks that a user represented by a token is allowed to access an object
1528 * represented by a security descriptor.
1530 * PARAMS
1531 * SecurityDescriptor [I] The security descriptor of the object to check.
1532 * ClientToken [I] Token of the user accessing the object.
1533 * DesiredAccess [I] The desired access to the object.
1534 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1535 * PrivilegeSet [I/O] Privileges used during the access check.
1536 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1537 * GrantedAccess [O] The actual access rights granted.
1538 * AccessStatus [O] The status of the access check.
1540 * RETURNS
1541 * NTSTATUS code.
1543 * NOTES
1544 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1545 * the maximum access rights allowed by the SD and returns them in
1546 * GrantedAccess.
1547 * The SecurityDescriptor must have a valid owner and groups present,
1548 * otherwise the function will fail.
1550 NTSTATUS WINAPI
1551 NtAccessCheck(
1552 PSECURITY_DESCRIPTOR SecurityDescriptor,
1553 HANDLE ClientToken,
1554 ACCESS_MASK DesiredAccess,
1555 PGENERIC_MAPPING GenericMapping,
1556 PPRIVILEGE_SET PrivilegeSet,
1557 PULONG ReturnLength,
1558 PULONG GrantedAccess,
1559 NTSTATUS *AccessStatus)
1561 NTSTATUS status;
1563 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1564 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1565 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1567 if (!PrivilegeSet || !ReturnLength)
1568 return STATUS_ACCESS_VIOLATION;
1570 SERVER_START_REQ( access_check )
1572 struct security_descriptor sd;
1573 PSID owner;
1574 PSID group;
1575 PACL sacl;
1576 PACL dacl;
1577 BOOLEAN defaulted, present;
1578 DWORD revision;
1579 SECURITY_DESCRIPTOR_CONTROL control;
1581 req->handle = wine_server_obj_handle( ClientToken );
1582 req->desired_access = DesiredAccess;
1583 req->mapping_read = GenericMapping->GenericRead;
1584 req->mapping_write = GenericMapping->GenericWrite;
1585 req->mapping_execute = GenericMapping->GenericExecute;
1586 req->mapping_all = GenericMapping->GenericAll;
1588 /* marshal security descriptor */
1589 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1590 sd.control = control & ~SE_SELF_RELATIVE;
1591 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1592 sd.owner_len = RtlLengthSid( owner );
1593 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1594 sd.group_len = RtlLengthSid( group );
1595 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1596 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1597 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1598 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1600 wine_server_add_data( req, &sd, sizeof(sd) );
1601 wine_server_add_data( req, owner, sd.owner_len );
1602 wine_server_add_data( req, group, sd.group_len );
1603 wine_server_add_data( req, sacl, sd.sacl_len );
1604 wine_server_add_data( req, dacl, sd.dacl_len );
1606 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1608 status = wine_server_call( req );
1610 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1611 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1613 if (status == STATUS_SUCCESS)
1615 *AccessStatus = reply->access_status;
1616 *GrantedAccess = reply->access_granted;
1619 SERVER_END_REQ;
1621 return status;
1624 /******************************************************************************
1625 * NtSetSecurityObject [NTDLL.@]
1626 * ZwSetSecurityObject [NTDLL.@]
1628 * Sets specified parts of the object's security descriptor.
1630 * PARAMS
1631 * Handle [I] Handle to the object to change security descriptor of.
1632 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1633 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1635 * RETURNS
1636 * NTSTATUS code.
1639 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1640 SECURITY_INFORMATION SecurityInformation,
1641 PSECURITY_DESCRIPTOR SecurityDescriptor)
1643 NTSTATUS status;
1644 struct security_descriptor sd;
1645 PACL dacl = NULL, sacl = NULL;
1646 PSID owner = NULL, group = NULL;
1647 BOOLEAN defaulted, present;
1648 DWORD revision;
1649 SECURITY_DESCRIPTOR_CONTROL control;
1651 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1653 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1655 memset( &sd, 0, sizeof(sd) );
1656 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1657 if (status != STATUS_SUCCESS) return status;
1658 sd.control = control & ~SE_SELF_RELATIVE;
1660 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1662 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1663 if (status != STATUS_SUCCESS) return status;
1664 if (!(sd.owner_len = RtlLengthSid( owner )))
1665 return STATUS_INVALID_SECURITY_DESCR;
1668 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1670 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1671 if (status != STATUS_SUCCESS) return status;
1672 if (!(sd.group_len = RtlLengthSid( group )))
1673 return STATUS_INVALID_SECURITY_DESCR;
1676 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1678 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1679 if (status != STATUS_SUCCESS) return status;
1680 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1681 sd.control |= SE_SACL_PRESENT;
1684 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1686 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1687 if (status != STATUS_SUCCESS) return status;
1688 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1689 sd.control |= SE_DACL_PRESENT;
1692 SERVER_START_REQ( set_security_object )
1694 req->handle = wine_server_obj_handle( Handle );
1695 req->security_info = SecurityInformation;
1697 wine_server_add_data( req, &sd, sizeof(sd) );
1698 wine_server_add_data( req, owner, sd.owner_len );
1699 wine_server_add_data( req, group, sd.group_len );
1700 wine_server_add_data( req, sacl, sd.sacl_len );
1701 wine_server_add_data( req, dacl, sd.dacl_len );
1702 status = wine_server_call( req );
1704 SERVER_END_REQ;
1706 return status;
1709 /******************************************************************************
1710 * RtlConvertSidToUnicodeString (NTDLL.@)
1712 * The returned SID is used to access the USER registry hive usually
1714 * the native function returns something like
1715 * "S-1-5-21-0000000000-000000000-0000000000-500";
1717 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1718 PUNICODE_STRING String,
1719 PSID pSid,
1720 BOOLEAN AllocateString)
1722 static const WCHAR formatW[] = {'-','%','u',0};
1723 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1724 WCHAR *p = buffer;
1725 const SID *sid = pSid;
1726 DWORD i, len;
1728 *p++ = 'S';
1729 p += sprintfW( p, formatW, sid->Revision );
1730 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1731 sid->IdentifierAuthority.Value[4] ),
1732 MAKEWORD( sid->IdentifierAuthority.Value[3],
1733 sid->IdentifierAuthority.Value[2] )));
1734 for (i = 0; i < sid->SubAuthorityCount; i++)
1735 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1737 len = (p + 1 - buffer) * sizeof(WCHAR);
1739 String->Length = len - sizeof(WCHAR);
1740 if (AllocateString)
1742 String->MaximumLength = len;
1743 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1744 return STATUS_NO_MEMORY;
1746 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1748 memcpy( String->Buffer, buffer, len );
1749 return STATUS_SUCCESS;
1752 /******************************************************************************
1753 * RtlQueryInformationAcl (NTDLL.@)
1755 NTSTATUS WINAPI RtlQueryInformationAcl(
1756 PACL pAcl,
1757 LPVOID pAclInformation,
1758 DWORD nAclInformationLength,
1759 ACL_INFORMATION_CLASS dwAclInformationClass)
1761 NTSTATUS status = STATUS_SUCCESS;
1763 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1764 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1766 switch (dwAclInformationClass)
1768 case AclRevisionInformation:
1770 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1772 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1773 status = STATUS_INVALID_PARAMETER;
1774 else
1775 paclrev->AclRevision = pAcl->AclRevision;
1777 break;
1780 case AclSizeInformation:
1782 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1784 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1785 status = STATUS_INVALID_PARAMETER;
1786 else
1788 paclsize->AceCount = pAcl->AceCount;
1789 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1790 if (pAcl->AclSize < paclsize->AclBytesInUse)
1792 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1793 paclsize->AclBytesFree = 0;
1794 paclsize->AclBytesInUse = pAcl->AclSize;
1796 else
1797 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1800 break;
1803 default:
1804 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1805 status = STATUS_INVALID_PARAMETER;
1808 return status;
1811 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1812 PSECURITY_DESCRIPTOR pdesc,
1813 PSECURITY_DESCRIPTOR cdesc,
1814 PSECURITY_DESCRIPTOR* ndesc,
1815 GUID* objtype,
1816 BOOL isdir,
1817 PGENERIC_MAPPING genmap )
1819 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1821 return FALSE;