msvcrt: Add __swprintf_l.
[wine.git] / dlls / ntdll / sec.c
blob360a579ceb9a0a12915a4af6400717257f39c8bd
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 FALSE;
1149 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1151 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1152 return FALSE;
1153 *x = ace;
1154 return TRUE;
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 (!RtlValidAcl(acl))
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 if (rev > acl->AclRevision)
1184 acl->AclRevision = rev;
1185 return STATUS_SUCCESS;
1188 /**************************************************************************
1189 * RtlDeleteAce [NTDLL.@]
1191 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1193 NTSTATUS status;
1194 PACE_HEADER pAce;
1196 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1198 if (STATUS_SUCCESS == status)
1200 PACE_HEADER pcAce;
1201 DWORD len = 0;
1203 /* skip over the ACE we are deleting */
1204 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1205 dwAceIndex++;
1207 /* calculate the length of the rest */
1208 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1210 len += pcAce->AceSize;
1211 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1214 /* slide them all backwards */
1215 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1216 pAcl->AceCount--;
1219 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1221 return status;
1224 /******************************************************************************
1225 * RtlAddAccessAllowedAce [NTDLL.@]
1227 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1228 IN OUT PACL pAcl,
1229 IN DWORD dwAceRevision,
1230 IN DWORD AccessMask,
1231 IN PSID pSid)
1233 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1236 /******************************************************************************
1237 * RtlAddAccessAllowedAceEx [NTDLL.@]
1239 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1240 IN OUT PACL pAcl,
1241 IN DWORD dwAceRevision,
1242 IN DWORD AceFlags,
1243 IN DWORD AccessMask,
1244 IN PSID pSid)
1246 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1248 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1249 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1252 /******************************************************************************
1253 * RtlAddAccessDeniedAce [NTDLL.@]
1255 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1256 IN OUT PACL pAcl,
1257 IN DWORD dwAceRevision,
1258 IN DWORD AccessMask,
1259 IN PSID pSid)
1261 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1264 /******************************************************************************
1265 * RtlAddAccessDeniedAceEx [NTDLL.@]
1267 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1268 IN OUT PACL pAcl,
1269 IN DWORD dwAceRevision,
1270 IN DWORD AceFlags,
1271 IN DWORD AccessMask,
1272 IN PSID pSid)
1274 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1276 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1277 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1280 /**************************************************************************
1281 * RtlAddAuditAccessAce [NTDLL.@]
1283 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1284 IN OUT PACL pAcl,
1285 IN DWORD dwAceRevision,
1286 IN DWORD dwAceFlags,
1287 IN DWORD dwAccessMask,
1288 IN PSID pSid,
1289 IN BOOL bAuditSuccess,
1290 IN BOOL bAuditFailure)
1292 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1293 pSid,bAuditSuccess,bAuditFailure);
1295 if (bAuditSuccess)
1296 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1298 if (bAuditFailure)
1299 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1301 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1302 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1305 /**************************************************************************
1306 * RtlAddAuditAccessAce [NTDLL.@]
1308 NTSTATUS WINAPI RtlAddAuditAccessAce(
1309 IN OUT PACL pAcl,
1310 IN DWORD dwAceRevision,
1311 IN DWORD dwAccessMask,
1312 IN PSID pSid,
1313 IN BOOL bAuditSuccess,
1314 IN BOOL bAuditFailure)
1316 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1319 /******************************************************************************
1320 * RtlValidAcl [NTDLL.@]
1322 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1324 BOOLEAN ret;
1325 TRACE("(%p)\n", pAcl);
1327 __TRY
1329 PACE_HEADER ace;
1330 int i;
1332 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1333 pAcl->AclRevision > MAX_ACL_REVISION)
1334 ret = FALSE;
1335 else
1337 ace = (PACE_HEADER)(pAcl+1);
1338 ret = TRUE;
1339 for (i=0;i<=pAcl->AceCount;i++)
1341 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1343 ret = FALSE;
1344 break;
1346 if (i != pAcl->AceCount)
1347 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1351 __EXCEPT_PAGE_FAULT
1353 WARN("(%p): invalid pointer!\n", pAcl);
1354 return FALSE;
1356 __ENDTRY
1357 return ret;
1360 /******************************************************************************
1361 * RtlGetAce [NTDLL.@]
1363 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1365 PACE_HEADER ace;
1367 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1369 if (dwAceIndex >= pAcl->AceCount)
1370 return STATUS_INVALID_PARAMETER;
1372 ace = (PACE_HEADER)(pAcl + 1);
1373 for (;dwAceIndex;dwAceIndex--)
1374 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1376 *pAce = ace;
1378 return STATUS_SUCCESS;
1382 * misc
1385 /******************************************************************************
1386 * RtlAdjustPrivilege [NTDLL.@]
1388 * Enables or disables a privilege from the calling thread or process.
1390 * PARAMS
1391 * Privilege [I] Privilege index to change.
1392 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1393 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1394 * Enabled [O] Whether privilege was previously enabled or disabled.
1396 * RETURNS
1397 * Success: STATUS_SUCCESS.
1398 * Failure: NTSTATUS code.
1400 * SEE ALSO
1401 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1404 NTSTATUS WINAPI
1405 RtlAdjustPrivilege(ULONG Privilege,
1406 BOOLEAN Enable,
1407 BOOLEAN CurrentThread,
1408 PBOOLEAN Enabled)
1410 TOKEN_PRIVILEGES NewState;
1411 TOKEN_PRIVILEGES OldState;
1412 ULONG ReturnLength;
1413 HANDLE TokenHandle;
1414 NTSTATUS Status;
1416 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1417 CurrentThread ? "TRUE" : "FALSE", Enabled);
1419 if (CurrentThread)
1421 Status = NtOpenThreadToken(GetCurrentThread(),
1422 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1423 FALSE,
1424 &TokenHandle);
1426 else
1428 Status = NtOpenProcessToken(GetCurrentProcess(),
1429 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1430 &TokenHandle);
1433 if (!NT_SUCCESS(Status))
1435 WARN("Retrieving token handle failed (Status %x)\n", Status);
1436 return Status;
1439 OldState.PrivilegeCount = 1;
1441 NewState.PrivilegeCount = 1;
1442 NewState.Privileges[0].Luid.LowPart = Privilege;
1443 NewState.Privileges[0].Luid.HighPart = 0;
1444 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1446 Status = NtAdjustPrivilegesToken(TokenHandle,
1447 FALSE,
1448 &NewState,
1449 sizeof(TOKEN_PRIVILEGES),
1450 &OldState,
1451 &ReturnLength);
1452 NtClose (TokenHandle);
1453 if (Status == STATUS_NOT_ALL_ASSIGNED)
1455 TRACE("Failed to assign all privileges\n");
1456 return STATUS_PRIVILEGE_NOT_HELD;
1458 if (!NT_SUCCESS(Status))
1460 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1461 return Status;
1464 if (OldState.PrivilegeCount == 0)
1465 *Enabled = Enable;
1466 else
1467 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1469 return STATUS_SUCCESS;
1472 /******************************************************************************
1473 * RtlImpersonateSelf [NTDLL.@]
1475 * Makes an impersonation token that represents the process user and assigns
1476 * to the current thread.
1478 * PARAMS
1479 * ImpersonationLevel [I] Level at which to impersonate.
1481 * RETURNS
1482 * Success: STATUS_SUCCESS.
1483 * Failure: NTSTATUS code.
1485 NTSTATUS WINAPI
1486 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1488 NTSTATUS Status;
1489 OBJECT_ATTRIBUTES ObjectAttributes;
1490 HANDLE ProcessToken;
1491 HANDLE ImpersonationToken;
1493 TRACE("(%08x)\n", ImpersonationLevel);
1495 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1496 &ProcessToken);
1497 if (Status != STATUS_SUCCESS)
1498 return Status;
1500 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1502 Status = NtDuplicateToken( ProcessToken,
1503 TOKEN_IMPERSONATE,
1504 &ObjectAttributes,
1505 ImpersonationLevel,
1506 TokenImpersonation,
1507 &ImpersonationToken );
1508 if (Status != STATUS_SUCCESS)
1510 NtClose( ProcessToken );
1511 return Status;
1514 Status = NtSetInformationThread( GetCurrentThread(),
1515 ThreadImpersonationToken,
1516 &ImpersonationToken,
1517 sizeof(ImpersonationToken) );
1519 NtClose( ImpersonationToken );
1520 NtClose( ProcessToken );
1522 return Status;
1525 /******************************************************************************
1526 * NtImpersonateAnonymousToken [NTDLL.@]
1528 NTSTATUS WINAPI
1529 NtImpersonateAnonymousToken(HANDLE thread)
1531 FIXME("(%p): stub\n", thread);
1532 return STATUS_NOT_IMPLEMENTED;
1535 /******************************************************************************
1536 * NtAccessCheck [NTDLL.@]
1537 * ZwAccessCheck [NTDLL.@]
1539 * Checks that a user represented by a token is allowed to access an object
1540 * represented by a security descriptor.
1542 * PARAMS
1543 * SecurityDescriptor [I] The security descriptor of the object to check.
1544 * ClientToken [I] Token of the user accessing the object.
1545 * DesiredAccess [I] The desired access to the object.
1546 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1547 * PrivilegeSet [I/O] Privileges used during the access check.
1548 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1549 * GrantedAccess [O] The actual access rights granted.
1550 * AccessStatus [O] The status of the access check.
1552 * RETURNS
1553 * NTSTATUS code.
1555 * NOTES
1556 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1557 * the maximum access rights allowed by the SD and returns them in
1558 * GrantedAccess.
1559 * The SecurityDescriptor must have a valid owner and groups present,
1560 * otherwise the function will fail.
1562 NTSTATUS WINAPI
1563 NtAccessCheck(
1564 PSECURITY_DESCRIPTOR SecurityDescriptor,
1565 HANDLE ClientToken,
1566 ACCESS_MASK DesiredAccess,
1567 PGENERIC_MAPPING GenericMapping,
1568 PPRIVILEGE_SET PrivilegeSet,
1569 PULONG ReturnLength,
1570 PULONG GrantedAccess,
1571 NTSTATUS *AccessStatus)
1573 NTSTATUS status;
1575 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1576 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1577 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1579 if (!PrivilegeSet || !ReturnLength)
1580 return STATUS_ACCESS_VIOLATION;
1582 SERVER_START_REQ( access_check )
1584 struct security_descriptor sd;
1585 PSID owner;
1586 PSID group;
1587 PACL sacl;
1588 PACL dacl;
1589 BOOLEAN defaulted, present;
1590 DWORD revision;
1591 SECURITY_DESCRIPTOR_CONTROL control;
1593 req->handle = wine_server_obj_handle( ClientToken );
1594 req->desired_access = DesiredAccess;
1595 req->mapping_read = GenericMapping->GenericRead;
1596 req->mapping_write = GenericMapping->GenericWrite;
1597 req->mapping_execute = GenericMapping->GenericExecute;
1598 req->mapping_all = GenericMapping->GenericAll;
1600 /* marshal security descriptor */
1601 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1602 sd.control = control & ~SE_SELF_RELATIVE;
1603 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1604 sd.owner_len = RtlLengthSid( owner );
1605 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1606 sd.group_len = RtlLengthSid( group );
1607 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1608 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1609 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1610 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1612 wine_server_add_data( req, &sd, sizeof(sd) );
1613 wine_server_add_data( req, owner, sd.owner_len );
1614 wine_server_add_data( req, group, sd.group_len );
1615 wine_server_add_data( req, sacl, sd.sacl_len );
1616 wine_server_add_data( req, dacl, sd.dacl_len );
1618 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1620 status = wine_server_call( req );
1622 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1623 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1625 if (status == STATUS_SUCCESS)
1627 *AccessStatus = reply->access_status;
1628 *GrantedAccess = reply->access_granted;
1631 SERVER_END_REQ;
1633 return status;
1636 /******************************************************************************
1637 * NtSetSecurityObject [NTDLL.@]
1638 * ZwSetSecurityObject [NTDLL.@]
1640 * Sets specified parts of the object's security descriptor.
1642 * PARAMS
1643 * Handle [I] Handle to the object to change security descriptor of.
1644 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1645 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1647 * RETURNS
1648 * NTSTATUS code.
1651 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1652 SECURITY_INFORMATION SecurityInformation,
1653 PSECURITY_DESCRIPTOR SecurityDescriptor)
1655 NTSTATUS status;
1656 struct security_descriptor sd;
1657 PACL dacl = NULL, sacl = NULL;
1658 PSID owner = NULL, group = NULL;
1659 BOOLEAN defaulted, present;
1660 DWORD revision;
1661 SECURITY_DESCRIPTOR_CONTROL control;
1663 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1665 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1667 memset( &sd, 0, sizeof(sd) );
1668 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1669 if (status != STATUS_SUCCESS) return status;
1670 sd.control = control & ~SE_SELF_RELATIVE;
1672 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1674 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1675 if (status != STATUS_SUCCESS) return status;
1676 if (!(sd.owner_len = RtlLengthSid( owner )))
1677 return STATUS_INVALID_SECURITY_DESCR;
1680 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1682 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1683 if (status != STATUS_SUCCESS) return status;
1684 if (!(sd.group_len = RtlLengthSid( group )))
1685 return STATUS_INVALID_SECURITY_DESCR;
1688 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1690 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1691 if (status != STATUS_SUCCESS) return status;
1692 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1693 sd.control |= SE_SACL_PRESENT;
1696 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1698 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1699 if (status != STATUS_SUCCESS) return status;
1700 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1701 sd.control |= SE_DACL_PRESENT;
1704 SERVER_START_REQ( set_security_object )
1706 req->handle = wine_server_obj_handle( Handle );
1707 req->security_info = SecurityInformation;
1709 wine_server_add_data( req, &sd, sizeof(sd) );
1710 wine_server_add_data( req, owner, sd.owner_len );
1711 wine_server_add_data( req, group, sd.group_len );
1712 wine_server_add_data( req, sacl, sd.sacl_len );
1713 wine_server_add_data( req, dacl, sd.dacl_len );
1714 status = wine_server_call( req );
1716 SERVER_END_REQ;
1718 return status;
1721 /******************************************************************************
1722 * RtlConvertSidToUnicodeString (NTDLL.@)
1724 * The returned SID is used to access the USER registry hive usually
1726 * the native function returns something like
1727 * "S-1-5-21-0000000000-000000000-0000000000-500";
1729 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1730 PUNICODE_STRING String,
1731 PSID pSid,
1732 BOOLEAN AllocateString)
1734 static const WCHAR formatW[] = {'-','%','u',0};
1735 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1736 WCHAR *p = buffer;
1737 const SID *sid = pSid;
1738 DWORD i, len;
1740 *p++ = 'S';
1741 p += sprintfW( p, formatW, sid->Revision );
1742 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1743 sid->IdentifierAuthority.Value[4] ),
1744 MAKEWORD( sid->IdentifierAuthority.Value[3],
1745 sid->IdentifierAuthority.Value[2] )));
1746 for (i = 0; i < sid->SubAuthorityCount; i++)
1747 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1749 len = (p + 1 - buffer) * sizeof(WCHAR);
1751 String->Length = len - sizeof(WCHAR);
1752 if (AllocateString)
1754 String->MaximumLength = len;
1755 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1756 return STATUS_NO_MEMORY;
1758 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1760 memcpy( String->Buffer, buffer, len );
1761 return STATUS_SUCCESS;
1764 /******************************************************************************
1765 * RtlQueryInformationAcl (NTDLL.@)
1767 NTSTATUS WINAPI RtlQueryInformationAcl(
1768 PACL pAcl,
1769 LPVOID pAclInformation,
1770 DWORD nAclInformationLength,
1771 ACL_INFORMATION_CLASS dwAclInformationClass)
1773 NTSTATUS status = STATUS_SUCCESS;
1775 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1776 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1778 switch (dwAclInformationClass)
1780 case AclRevisionInformation:
1782 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1784 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1785 status = STATUS_INVALID_PARAMETER;
1786 else
1787 paclrev->AclRevision = pAcl->AclRevision;
1789 break;
1792 case AclSizeInformation:
1794 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1796 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1797 status = STATUS_INVALID_PARAMETER;
1798 else
1800 paclsize->AceCount = pAcl->AceCount;
1801 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1802 if (pAcl->AclSize < paclsize->AclBytesInUse)
1804 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1805 paclsize->AclBytesFree = 0;
1806 paclsize->AclBytesInUse = pAcl->AclSize;
1808 else
1809 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1812 break;
1815 default:
1816 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1817 status = STATUS_INVALID_PARAMETER;
1820 return status;
1823 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1824 PSECURITY_DESCRIPTOR pdesc,
1825 PSECURITY_DESCRIPTOR cdesc,
1826 PSECURITY_DESCRIPTOR* ndesc,
1827 GUID* objtype,
1828 BOOL isdir,
1829 PGENERIC_MAPPING genmap )
1831 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1833 return FALSE;