devenum: Implement IMoniker::GetClassID().
[wine.git] / dlls / ntdll / sec.c
blob3f7aa79323668427108c25a78a05609ba89a3282
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "ntdll_misc.h"
39 #include "wine/exception.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
50 /* helper function to retrieve active length of an ACL */
51 static size_t acl_bytesInUse(PACL pAcl)
53 int i;
54 size_t bytesInUse = sizeof(ACL);
55 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
56 for (i = 0; i < pAcl->AceCount; i++)
58 bytesInUse += ace->AceSize;
59 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
61 return bytesInUse;
64 /* helper function to copy an ACL */
65 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
67 DWORD size;
69 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
70 return FALSE;
72 size = pSourceAcl->AclSize;
73 if (nDestinationAclLength < size)
74 return FALSE;
76 memmove(pDestinationAcl, pSourceAcl, size);
77 return TRUE;
80 /* generically adds an ACE to an ACL */
81 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
82 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
84 ACE_HEADER *pAceHeader;
85 DWORD dwLengthSid;
86 DWORD dwAceSize;
87 DWORD *pAccessMask;
88 DWORD *pSidStart;
90 if (!RtlValidSid(pSid))
91 return STATUS_INVALID_SID;
93 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
94 return STATUS_REVISION_MISMATCH;
96 if (!RtlValidAcl(pAcl))
97 return STATUS_INVALID_ACL;
99 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
100 return STATUS_INVALID_ACL;
102 if (!pAceHeader)
103 return STATUS_ALLOTTED_SPACE_EXCEEDED;
105 /* calculate generic size of the ACE */
106 dwLengthSid = RtlLengthSid(pSid);
107 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
108 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
109 return STATUS_ALLOTTED_SPACE_EXCEEDED;
111 /* fill the new ACE */
112 pAceHeader->AceType = dwAceType;
113 pAceHeader->AceFlags = dwAceFlags;
114 pAceHeader->AceSize = dwAceSize;
116 /* skip past the ACE_HEADER of the ACE */
117 pAccessMask = (DWORD *)(pAceHeader + 1);
118 *pAccessMask = dwAccessMask;
120 /* skip past ACE->Mask */
121 pSidStart = pAccessMask + 1;
122 RtlCopySid(dwLengthSid, pSidStart, pSid);
124 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
125 pAcl->AceCount++;
127 return STATUS_SUCCESS;
131 * SID FUNCTIONS
134 /******************************************************************************
135 * RtlAllocateAndInitializeSid [NTDLL.@]
138 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
139 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
140 BYTE nSubAuthorityCount,
141 DWORD nSubAuthority0, DWORD nSubAuthority1,
142 DWORD nSubAuthority2, DWORD nSubAuthority3,
143 DWORD nSubAuthority4, DWORD nSubAuthority5,
144 DWORD nSubAuthority6, DWORD nSubAuthority7,
145 PSID *pSid )
147 SID *tmp_sid;
149 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
150 pIdentifierAuthority,nSubAuthorityCount,
151 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
152 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
154 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
156 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
157 RtlLengthRequiredSid(nSubAuthorityCount))))
158 return STATUS_NO_MEMORY;
160 tmp_sid->Revision = SID_REVISION;
162 if (pIdentifierAuthority)
163 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
164 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
166 switch( nSubAuthorityCount )
168 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
169 /* fall through */
170 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
171 /* fall through */
172 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
173 /* fall through */
174 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
175 /* fall through */
176 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
177 /* fall through */
178 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
179 /* fall through */
180 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
181 /* fall through */
182 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
183 break;
185 *pSid = tmp_sid;
186 return STATUS_SUCCESS;
189 /******************************************************************************
190 * RtlEqualSid [NTDLL.@]
192 * Determine if two SIDs are equal.
194 * PARAMS
195 * pSid1 [I] Source SID
196 * pSid2 [I] SID to compare with
198 * RETURNS
199 * TRUE, if pSid1 is equal to pSid2,
200 * FALSE otherwise.
202 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
204 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
205 return FALSE;
207 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
208 return FALSE;
210 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
211 return FALSE;
213 return TRUE;
216 /******************************************************************************
217 * RtlEqualPrefixSid [NTDLL.@]
219 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
221 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
222 return FALSE;
224 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
225 return FALSE;
227 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
228 return FALSE;
230 return TRUE;
234 /******************************************************************************
235 * RtlFreeSid [NTDLL.@]
237 * Free the resources used by a SID.
239 * PARAMS
240 * pSid [I] SID to Free.
242 * RETURNS
243 * STATUS_SUCCESS.
245 DWORD WINAPI RtlFreeSid(PSID pSid)
247 TRACE("(%p)\n", pSid);
248 RtlFreeHeap( GetProcessHeap(), 0, pSid );
249 return STATUS_SUCCESS;
252 /**************************************************************************
253 * RtlLengthRequiredSid [NTDLL.@]
255 * Determine the amount of memory a SID will use
257 * PARAMS
258 * nrofsubauths [I] Number of Sub Authorities in the SID.
260 * RETURNS
261 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
263 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
265 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
268 /**************************************************************************
269 * RtlLengthSid [NTDLL.@]
271 * Determine the amount of memory a SID is using
273 * PARAMS
274 * pSid [I] SID to get the size of.
276 * RETURNS
277 * The size, in bytes, of pSid.
279 DWORD WINAPI RtlLengthSid(PSID pSid)
281 TRACE("sid=%p\n",pSid);
282 if (!pSid) return 0;
283 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
286 /**************************************************************************
287 * RtlInitializeSid [NTDLL.@]
289 * Initialise a SID.
291 * PARAMS
292 * pSid [I] SID to initialise
293 * pIdentifierAuthority [I] Identifier Authority
294 * nSubAuthorityCount [I] Number of Sub Authorities
296 * RETURNS
297 * Success: TRUE. pSid is initialised with the details given.
298 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
300 BOOL WINAPI RtlInitializeSid(
301 PSID pSid,
302 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
303 BYTE nSubAuthorityCount)
305 int i;
306 SID* pisid=pSid;
308 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
309 return FALSE;
311 pisid->Revision = SID_REVISION;
312 pisid->SubAuthorityCount = nSubAuthorityCount;
313 if (pIdentifierAuthority)
314 pisid->IdentifierAuthority = *pIdentifierAuthority;
316 for (i = 0; i < nSubAuthorityCount; i++)
317 *RtlSubAuthoritySid(pSid, i) = 0;
319 return TRUE;
322 /**************************************************************************
323 * RtlSubAuthoritySid [NTDLL.@]
325 * Return the Sub Authority of a SID
327 * PARAMS
328 * pSid [I] SID to get the Sub Authority from.
329 * nSubAuthority [I] Sub Authority number.
331 * RETURNS
332 * A pointer to The Sub Authority value of pSid.
334 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
336 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
339 /**************************************************************************
340 * RtlIdentifierAuthoritySid [NTDLL.@]
342 * Return the Identifier Authority of a SID.
344 * PARAMS
345 * pSid [I] SID to get the Identifier Authority from.
347 * RETURNS
348 * A pointer to the Identifier Authority value of pSid.
350 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
352 return &(((SID*)pSid)->IdentifierAuthority);
355 /**************************************************************************
356 * RtlSubAuthorityCountSid [NTDLL.@]
358 * Get the number of Sub Authorities in a SID.
360 * PARAMS
361 * pSid [I] SID to get the count from.
363 * RETURNS
364 * A pointer to the Sub Authority count of pSid.
366 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
368 return &(((SID*)pSid)->SubAuthorityCount);
371 /**************************************************************************
372 * RtlCopySid [NTDLL.@]
374 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
376 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
377 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
378 return FALSE;
380 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
381 return FALSE;
383 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
384 return TRUE;
386 /******************************************************************************
387 * RtlValidSid [NTDLL.@]
389 * Determine if a SID is valid.
391 * PARAMS
392 * pSid [I] SID to check
394 * RETURNS
395 * TRUE if pSid is valid,
396 * FALSE otherwise.
398 BOOLEAN WINAPI RtlValidSid( PSID pSid )
400 BOOL ret;
401 __TRY
403 ret = TRUE;
404 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
405 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
407 ret = FALSE;
410 __EXCEPT_PAGE_FAULT
412 WARN("(%p): invalid pointer!\n", pSid);
413 return FALSE;
415 __ENDTRY
416 return ret;
421 * security descriptor functions
424 /**************************************************************************
425 * RtlCreateSecurityDescriptor [NTDLL.@]
427 * Initialise a SECURITY_DESCRIPTOR.
429 * PARAMS
430 * lpsd [O] Descriptor to initialise.
431 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
433 * RETURNS
434 * Success: STATUS_SUCCESS.
435 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
437 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
438 PSECURITY_DESCRIPTOR lpsd,
439 DWORD rev)
441 if (rev!=SECURITY_DESCRIPTOR_REVISION)
442 return STATUS_UNKNOWN_REVISION;
443 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
444 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
445 return STATUS_SUCCESS;
448 /**************************************************************************
449 * RtlCopySecurityDescriptor [NTDLL.@]
451 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
453 * PARAMS
454 * pSourceSD [O] SD to copy from.
455 * pDestinationSD [I] Destination SD.
457 * RETURNS
458 * Success: STATUS_SUCCESS.
459 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
461 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
463 PSID Owner, Group;
464 PACL Dacl, Sacl;
465 DWORD length;
467 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
469 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
470 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
472 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
473 return STATUS_UNKNOWN_REVISION;
475 *dst = *src;
476 if (src->Owner)
478 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
479 length = RtlLengthSid( Owner );
480 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
482 if (src->Group)
484 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
485 length = RtlLengthSid( Group );
486 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
488 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
490 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
491 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
493 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
495 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
496 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
499 else
501 SECURITY_DESCRIPTOR *src = pSourceSD;
502 SECURITY_DESCRIPTOR *dst = pDestinationSD;
504 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
505 return STATUS_UNKNOWN_REVISION;
507 *dst = *src;
508 if (src->Owner)
510 length = RtlLengthSid( src->Owner );
511 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
512 RtlCopySid(length, dst->Owner, src->Owner);
514 if (src->Group)
516 length = RtlLengthSid( src->Group );
517 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 RtlCopySid(length, dst->Group, src->Group);
520 if (src->Control & SE_SACL_PRESENT)
522 length = src->Sacl->AclSize;
523 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
524 copy_acl(length, dst->Sacl, src->Sacl);
526 if (src->Control & SE_DACL_PRESENT)
528 length = src->Dacl->AclSize;
529 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
530 copy_acl(length, dst->Dacl, src->Dacl);
534 return STATUS_SUCCESS;
537 /**************************************************************************
538 * RtlValidSecurityDescriptor [NTDLL.@]
540 * Determine if a SECURITY_DESCRIPTOR is valid.
542 * PARAMS
543 * SecurityDescriptor [I] Descriptor to check.
545 * RETURNS
546 * Success: STATUS_SUCCESS.
547 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
549 NTSTATUS WINAPI RtlValidSecurityDescriptor(
550 PSECURITY_DESCRIPTOR SecurityDescriptor)
552 if ( ! SecurityDescriptor )
553 return STATUS_INVALID_SECURITY_DESCR;
554 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
555 return STATUS_UNKNOWN_REVISION;
557 return STATUS_SUCCESS;
560 /**************************************************************************
561 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
563 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
564 ULONG length, SECURITY_INFORMATION info)
566 FIXME("%p,%u,%d: semi-stub\n", descriptor, length, info);
567 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
570 /**************************************************************************
571 * RtlLengthSecurityDescriptor [NTDLL.@]
573 ULONG WINAPI RtlLengthSecurityDescriptor(
574 PSECURITY_DESCRIPTOR pSecurityDescriptor)
576 ULONG size;
578 if ( pSecurityDescriptor == NULL )
579 return 0;
581 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
583 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
584 size = sizeof(*sd);
585 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
586 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
587 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
588 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
590 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
592 else
594 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
595 size = sizeof(*sd);
596 if (sd->Owner) size += RtlLengthSid( sd->Owner );
597 if (sd->Group) size += RtlLengthSid( sd->Group );
598 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
599 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
601 return size;
604 /******************************************************************************
605 * RtlGetDaclSecurityDescriptor [NTDLL.@]
608 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
609 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
610 OUT PBOOLEAN lpbDaclPresent,
611 OUT PACL *pDacl,
612 OUT PBOOLEAN lpbDaclDefaulted)
614 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
616 TRACE("(%p,%p,%p,%p)\n",
617 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
619 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
620 return STATUS_UNKNOWN_REVISION ;
622 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
624 if (lpsd->Control & SE_SELF_RELATIVE)
626 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
627 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
628 else *pDacl = NULL;
630 else *pDacl = lpsd->Dacl;
632 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
634 else
636 *pDacl = NULL;
637 *lpbDaclDefaulted = 0;
640 return STATUS_SUCCESS;
643 /**************************************************************************
644 * RtlSetDaclSecurityDescriptor [NTDLL.@]
646 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
647 PSECURITY_DESCRIPTOR pSecurityDescriptor,
648 BOOLEAN daclpresent,
649 PACL dacl,
650 BOOLEAN dacldefaulted )
652 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
654 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
655 return STATUS_UNKNOWN_REVISION;
656 if (lpsd->Control & SE_SELF_RELATIVE)
657 return STATUS_INVALID_SECURITY_DESCR;
659 if (!daclpresent)
661 lpsd->Control &= ~SE_DACL_PRESENT;
662 return STATUS_SUCCESS;
665 lpsd->Control |= SE_DACL_PRESENT;
666 lpsd->Dacl = dacl;
668 if (dacldefaulted)
669 lpsd->Control |= SE_DACL_DEFAULTED;
670 else
671 lpsd->Control &= ~SE_DACL_DEFAULTED;
673 return STATUS_SUCCESS;
676 /******************************************************************************
677 * RtlGetSaclSecurityDescriptor [NTDLL.@]
680 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
681 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
682 OUT PBOOLEAN lpbSaclPresent,
683 OUT PACL *pSacl,
684 OUT PBOOLEAN lpbSaclDefaulted)
686 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
688 TRACE("(%p,%p,%p,%p)\n",
689 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
691 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
692 return STATUS_UNKNOWN_REVISION;
694 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
696 if (lpsd->Control & SE_SELF_RELATIVE)
698 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
699 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
700 else *pSacl = NULL;
702 else *pSacl = lpsd->Sacl;
704 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
706 return STATUS_SUCCESS;
709 /**************************************************************************
710 * RtlSetSaclSecurityDescriptor [NTDLL.@]
712 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
713 PSECURITY_DESCRIPTOR pSecurityDescriptor,
714 BOOLEAN saclpresent,
715 PACL sacl,
716 BOOLEAN sacldefaulted)
718 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
720 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
721 return STATUS_UNKNOWN_REVISION;
722 if (lpsd->Control & SE_SELF_RELATIVE)
723 return STATUS_INVALID_SECURITY_DESCR;
724 if (!saclpresent) {
725 lpsd->Control &= ~SE_SACL_PRESENT;
726 return 0;
728 lpsd->Control |= SE_SACL_PRESENT;
729 lpsd->Sacl = sacl;
730 if (sacldefaulted)
731 lpsd->Control |= SE_SACL_DEFAULTED;
732 else
733 lpsd->Control &= ~SE_SACL_DEFAULTED;
734 return STATUS_SUCCESS;
737 /**************************************************************************
738 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
740 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
741 PSECURITY_DESCRIPTOR pSecurityDescriptor,
742 PSID *Owner,
743 PBOOLEAN OwnerDefaulted)
745 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
747 if ( !lpsd || !Owner || !OwnerDefaulted )
748 return STATUS_INVALID_PARAMETER;
750 if ( lpsd->Control & SE_OWNER_DEFAULTED )
751 *OwnerDefaulted = TRUE;
752 else
753 *OwnerDefaulted = FALSE;
755 if (lpsd->Control & SE_SELF_RELATIVE)
757 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
758 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
759 else *Owner = NULL;
761 else
762 *Owner = lpsd->Owner;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
772 PSID owner,
773 BOOLEAN ownerdefaulted)
775 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
777 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
778 return STATUS_UNKNOWN_REVISION;
779 if (lpsd->Control & SE_SELF_RELATIVE)
780 return STATUS_INVALID_SECURITY_DESCR;
782 lpsd->Owner = owner;
783 if (ownerdefaulted)
784 lpsd->Control |= SE_OWNER_DEFAULTED;
785 else
786 lpsd->Control &= ~SE_OWNER_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlSetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
795 PSID group,
796 BOOLEAN groupdefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
801 return STATUS_UNKNOWN_REVISION;
802 if (lpsd->Control & SE_SELF_RELATIVE)
803 return STATUS_INVALID_SECURITY_DESCR;
805 lpsd->Group = group;
806 if (groupdefaulted)
807 lpsd->Control |= SE_GROUP_DEFAULTED;
808 else
809 lpsd->Control &= ~SE_GROUP_DEFAULTED;
810 return STATUS_SUCCESS;
813 /**************************************************************************
814 * RtlGetGroupSecurityDescriptor [NTDLL.@]
816 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
817 PSECURITY_DESCRIPTOR pSecurityDescriptor,
818 PSID *Group,
819 PBOOLEAN GroupDefaulted)
821 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
823 if ( !lpsd || !Group || !GroupDefaulted )
824 return STATUS_INVALID_PARAMETER;
826 if ( lpsd->Control & SE_GROUP_DEFAULTED )
827 *GroupDefaulted = TRUE;
828 else
829 *GroupDefaulted = FALSE;
831 if (lpsd->Control & SE_SELF_RELATIVE)
833 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
834 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
835 else *Group = NULL;
837 else
838 *Group = lpsd->Group;
840 return STATUS_SUCCESS;
843 /**************************************************************************
844 * RtlMakeSelfRelativeSD [NTDLL.@]
846 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
847 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
848 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
849 IN OUT LPDWORD lpdwBufferLength)
851 DWORD offsetRel;
852 ULONG length;
853 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
854 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
856 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
857 lpdwBufferLength ? *lpdwBufferLength: -1);
859 if (!lpdwBufferLength || !pAbs)
860 return STATUS_INVALID_PARAMETER;
862 length = RtlLengthSecurityDescriptor(pAbs);
863 if (*lpdwBufferLength < length)
865 *lpdwBufferLength = length;
866 return STATUS_BUFFER_TOO_SMALL;
869 if (!pRel)
870 return STATUS_INVALID_PARAMETER;
872 if (pAbs->Control & SE_SELF_RELATIVE)
874 memcpy(pRel, pAbs, length);
875 return STATUS_SUCCESS;
878 pRel->Revision = pAbs->Revision;
879 pRel->Sbz1 = pAbs->Sbz1;
880 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
882 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
883 if (pAbs->Owner)
885 pRel->Owner = offsetRel;
886 length = RtlLengthSid(pAbs->Owner);
887 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
888 offsetRel += length;
890 else
892 pRel->Owner = 0;
895 if (pAbs->Group)
897 pRel->Group = offsetRel;
898 length = RtlLengthSid(pAbs->Group);
899 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
900 offsetRel += length;
902 else
904 pRel->Group = 0;
907 if (pAbs->Sacl)
909 pRel->Sacl = offsetRel;
910 length = pAbs->Sacl->AclSize;
911 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
912 offsetRel += length;
914 else
916 pRel->Sacl = 0;
919 if (pAbs->Dacl)
921 pRel->Dacl = offsetRel;
922 length = pAbs->Dacl->AclSize;
923 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
925 else
927 pRel->Dacl = 0;
930 return STATUS_SUCCESS;
934 /**************************************************************************
935 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
937 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
938 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
939 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
940 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
941 OUT PACL pDacl,
942 OUT LPDWORD lpdwDaclSize,
943 OUT PACL pSacl,
944 OUT LPDWORD lpdwSaclSize,
945 OUT PSID pOwner,
946 OUT LPDWORD lpdwOwnerSize,
947 OUT PSID pPrimaryGroup,
948 OUT LPDWORD lpdwPrimaryGroupSize)
950 NTSTATUS status = STATUS_SUCCESS;
951 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
952 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
954 if (!pRel ||
955 !lpdwAbsoluteSecurityDescriptorSize ||
956 !lpdwDaclSize ||
957 !lpdwSaclSize ||
958 !lpdwOwnerSize ||
959 !lpdwPrimaryGroupSize ||
960 ~pRel->Control & SE_SELF_RELATIVE)
961 return STATUS_INVALID_PARAMETER;
963 /* Confirm buffers are sufficiently large */
964 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
966 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
967 status = STATUS_BUFFER_TOO_SMALL;
970 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
971 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
973 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
974 status = STATUS_BUFFER_TOO_SMALL;
977 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
978 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
980 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
981 status = STATUS_BUFFER_TOO_SMALL;
984 if (pRel->Owner &&
985 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
987 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
988 status = STATUS_BUFFER_TOO_SMALL;
991 if (pRel->Group &&
992 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
994 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
995 status = STATUS_BUFFER_TOO_SMALL;
998 if (status != STATUS_SUCCESS)
999 return status;
1001 /* Copy structures, and clear the ones we don't set */
1002 pAbs->Revision = pRel->Revision;
1003 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
1004 pAbs->Sacl = NULL;
1005 pAbs->Dacl = NULL;
1006 pAbs->Owner = NULL;
1007 pAbs->Group = NULL;
1009 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1011 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1013 memcpy(pSacl, pAcl, pAcl->AclSize);
1014 pAbs->Sacl = pSacl;
1017 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1019 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1020 memcpy(pDacl, pAcl, pAcl->AclSize);
1021 pAbs->Dacl = pDacl;
1024 if (pRel->Owner)
1026 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1027 memcpy(pOwner, psid, RtlLengthSid(psid));
1028 pAbs->Owner = pOwner;
1031 if (pRel->Group)
1033 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1034 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1035 pAbs->Group = pPrimaryGroup;
1038 return status;
1041 /******************************************************************************
1042 * RtlGetControlSecurityDescriptor (NTDLL.@)
1044 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1045 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1046 PSECURITY_DESCRIPTOR_CONTROL pControl,
1047 LPDWORD lpdwRevision)
1049 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1051 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1053 *lpdwRevision = lpsd->Revision;
1055 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1056 return STATUS_UNKNOWN_REVISION;
1058 *pControl = lpsd->Control;
1060 return STATUS_SUCCESS;
1063 /******************************************************************************
1064 * RtlSetControlSecurityDescriptor (NTDLL.@)
1066 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1067 PSECURITY_DESCRIPTOR SecurityDescriptor,
1068 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1069 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1071 SECURITY_DESCRIPTOR_CONTROL const immutable
1072 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1073 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1074 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1075 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1078 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1080 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1081 ControlBitsOfInterest, ControlBitsToSet);
1083 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1084 return STATUS_INVALID_PARAMETER;
1086 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1087 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1089 return STATUS_SUCCESS;
1093 /**************************************************************************
1094 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1096 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1097 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1098 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1099 PULONG BufferLength)
1101 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1103 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1104 SelfRelativeSecurityDescriptor, BufferLength);
1106 if (abs->Control & SE_SELF_RELATIVE)
1107 return STATUS_BAD_DESCRIPTOR_FORMAT;
1109 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1110 SelfRelativeSecurityDescriptor, BufferLength);
1115 * access control list's
1118 /**************************************************************************
1119 * RtlCreateAcl [NTDLL.@]
1121 * NOTES
1122 * This should return NTSTATUS
1124 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1126 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1128 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1129 return STATUS_INVALID_PARAMETER;
1130 if (size<sizeof(ACL))
1131 return STATUS_BUFFER_TOO_SMALL;
1132 if (size>0xFFFF)
1133 return STATUS_INVALID_PARAMETER;
1135 memset(acl,'\0',sizeof(ACL));
1136 acl->AclRevision = rev;
1137 acl->AclSize = size;
1138 acl->AceCount = 0;
1139 return STATUS_SUCCESS;
1142 /**************************************************************************
1143 * RtlFirstFreeAce [NTDLL.@]
1144 * looks for the AceCount+1 ACE, and if it is still within the alloced
1145 * ACL, return a pointer to it
1147 BOOLEAN WINAPI RtlFirstFreeAce(
1148 PACL acl,
1149 PACE_HEADER *x)
1151 PACE_HEADER ace;
1152 int i;
1154 *x = 0;
1155 ace = (PACE_HEADER)(acl+1);
1156 for (i=0;i<acl->AceCount;i++) {
1157 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1158 return FALSE;
1159 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1161 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1162 return FALSE;
1163 *x = ace;
1164 return TRUE;
1167 /**************************************************************************
1168 * RtlAddAce [NTDLL.@]
1170 NTSTATUS WINAPI RtlAddAce(
1171 PACL acl,
1172 DWORD rev,
1173 DWORD xnrofaces,
1174 PACE_HEADER acestart,
1175 DWORD acelen)
1177 PACE_HEADER ace,targetace;
1178 int nrofaces;
1180 if (!RtlValidAcl(acl))
1181 return STATUS_INVALID_PARAMETER;
1182 if (!RtlFirstFreeAce(acl,&targetace))
1183 return STATUS_INVALID_PARAMETER;
1184 nrofaces=0;ace=acestart;
1185 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1186 nrofaces++;
1187 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1189 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1190 return STATUS_INVALID_PARAMETER;
1191 memcpy(targetace,acestart,acelen);
1192 acl->AceCount+=nrofaces;
1193 if (rev > acl->AclRevision)
1194 acl->AclRevision = rev;
1195 return STATUS_SUCCESS;
1198 /**************************************************************************
1199 * RtlDeleteAce [NTDLL.@]
1201 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1203 NTSTATUS status;
1204 PACE_HEADER pAce;
1206 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1208 if (STATUS_SUCCESS == status)
1210 PACE_HEADER pcAce;
1211 DWORD len = 0;
1213 /* skip over the ACE we are deleting */
1214 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1215 dwAceIndex++;
1217 /* calculate the length of the rest */
1218 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1220 len += pcAce->AceSize;
1221 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1224 /* slide them all backwards */
1225 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1226 pAcl->AceCount--;
1229 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1231 return status;
1234 /******************************************************************************
1235 * RtlAddAccessAllowedAce [NTDLL.@]
1237 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1238 IN OUT PACL pAcl,
1239 IN DWORD dwAceRevision,
1240 IN DWORD AccessMask,
1241 IN PSID pSid)
1243 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1246 /******************************************************************************
1247 * RtlAddAccessAllowedAceEx [NTDLL.@]
1249 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1250 IN OUT PACL pAcl,
1251 IN DWORD dwAceRevision,
1252 IN DWORD AceFlags,
1253 IN DWORD AccessMask,
1254 IN PSID pSid)
1256 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1258 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1259 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1262 /******************************************************************************
1263 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1265 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1266 IN OUT PACL pAcl,
1267 IN DWORD dwAceRevision,
1268 IN DWORD dwAceFlags,
1269 IN DWORD dwAccessMask,
1270 IN GUID* pObjectTypeGuid,
1271 IN GUID* pInheritedObjectTypeGuid,
1272 IN PSID pSid)
1274 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1275 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1276 return STATUS_NOT_IMPLEMENTED;
1279 /******************************************************************************
1280 * RtlAddAccessDeniedAce [NTDLL.@]
1282 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1283 IN OUT PACL pAcl,
1284 IN DWORD dwAceRevision,
1285 IN DWORD AccessMask,
1286 IN PSID pSid)
1288 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1291 /******************************************************************************
1292 * RtlAddAccessDeniedAceEx [NTDLL.@]
1294 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1295 IN OUT PACL pAcl,
1296 IN DWORD dwAceRevision,
1297 IN DWORD AceFlags,
1298 IN DWORD AccessMask,
1299 IN PSID pSid)
1301 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1303 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1304 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1307 /******************************************************************************
1308 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1310 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1311 IN OUT PACL pAcl,
1312 IN DWORD dwAceRevision,
1313 IN DWORD dwAceFlags,
1314 IN DWORD dwAccessMask,
1315 IN GUID* pObjectTypeGuid,
1316 IN GUID* pInheritedObjectTypeGuid,
1317 IN PSID pSid)
1319 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1320 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1321 return STATUS_NOT_IMPLEMENTED;
1324 /**************************************************************************
1325 * RtlAddAuditAccessAce [NTDLL.@]
1327 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1328 IN OUT PACL pAcl,
1329 IN DWORD dwAceRevision,
1330 IN DWORD dwAceFlags,
1331 IN DWORD dwAccessMask,
1332 IN PSID pSid,
1333 IN BOOL bAuditSuccess,
1334 IN BOOL bAuditFailure)
1336 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1337 pSid,bAuditSuccess,bAuditFailure);
1339 if (bAuditSuccess)
1340 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1342 if (bAuditFailure)
1343 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1345 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1346 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1349 /**************************************************************************
1350 * RtlAddAuditAccessAce [NTDLL.@]
1352 NTSTATUS WINAPI RtlAddAuditAccessAce(
1353 IN OUT PACL pAcl,
1354 IN DWORD dwAceRevision,
1355 IN DWORD dwAccessMask,
1356 IN PSID pSid,
1357 IN BOOL bAuditSuccess,
1358 IN BOOL bAuditFailure)
1360 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1363 /******************************************************************************
1364 * RtlAddAuditAccessObjectAce [NTDLL.@]
1366 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1367 IN OUT PACL pAcl,
1368 IN DWORD dwAceRevision,
1369 IN DWORD dwAceFlags,
1370 IN DWORD dwAccessMask,
1371 IN GUID* pObjectTypeGuid,
1372 IN GUID* pInheritedObjectTypeGuid,
1373 IN PSID pSid,
1374 IN BOOL bAuditSuccess,
1375 IN BOOL bAuditFailure)
1377 FIXME("%p %x %x %x %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1378 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1379 return STATUS_NOT_IMPLEMENTED;
1382 /**************************************************************************
1383 * RtlAddMandatoryAce [NTDLL.@]
1385 NTSTATUS WINAPI RtlAddMandatoryAce(
1386 IN OUT PACL pAcl,
1387 IN DWORD dwAceRevision,
1388 IN DWORD dwAceFlags,
1389 IN DWORD dwMandatoryFlags,
1390 IN DWORD dwAceType,
1391 IN PSID pSid)
1393 static const DWORD valid_flags = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP |
1394 SYSTEM_MANDATORY_LABEL_NO_READ_UP |
1395 SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP;
1397 TRACE("(%p, %u, 0x%08x, 0x%08x, %u, %p)\n", pAcl, dwAceRevision, dwAceFlags,
1398 dwMandatoryFlags, dwAceType, pSid);
1400 if (dwAceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
1401 return STATUS_INVALID_PARAMETER;
1403 if (dwMandatoryFlags & ~valid_flags)
1404 return STATUS_INVALID_PARAMETER;
1406 return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, pSid, dwAceType);
1409 /******************************************************************************
1410 * RtlValidAcl [NTDLL.@]
1412 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1414 BOOLEAN ret;
1415 TRACE("(%p)\n", pAcl);
1417 __TRY
1419 PACE_HEADER ace;
1420 int i;
1422 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1423 pAcl->AclRevision > MAX_ACL_REVISION)
1424 ret = FALSE;
1425 else
1427 ace = (PACE_HEADER)(pAcl+1);
1428 ret = TRUE;
1429 for (i=0;i<=pAcl->AceCount;i++)
1431 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1433 ret = FALSE;
1434 break;
1436 if (i != pAcl->AceCount)
1437 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1441 __EXCEPT_PAGE_FAULT
1443 WARN("(%p): invalid pointer!\n", pAcl);
1444 return FALSE;
1446 __ENDTRY
1447 return ret;
1450 /******************************************************************************
1451 * RtlGetAce [NTDLL.@]
1453 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1455 PACE_HEADER ace;
1457 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1459 if (dwAceIndex >= pAcl->AceCount)
1460 return STATUS_INVALID_PARAMETER;
1462 ace = (PACE_HEADER)(pAcl + 1);
1463 for (;dwAceIndex;dwAceIndex--)
1464 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1466 *pAce = ace;
1468 return STATUS_SUCCESS;
1472 * misc
1475 /******************************************************************************
1476 * RtlAdjustPrivilege [NTDLL.@]
1478 * Enables or disables a privilege from the calling thread or process.
1480 * PARAMS
1481 * Privilege [I] Privilege index to change.
1482 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1483 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1484 * Enabled [O] Whether privilege was previously enabled or disabled.
1486 * RETURNS
1487 * Success: STATUS_SUCCESS.
1488 * Failure: NTSTATUS code.
1490 * SEE ALSO
1491 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1494 NTSTATUS WINAPI
1495 RtlAdjustPrivilege(ULONG Privilege,
1496 BOOLEAN Enable,
1497 BOOLEAN CurrentThread,
1498 PBOOLEAN Enabled)
1500 TOKEN_PRIVILEGES NewState;
1501 TOKEN_PRIVILEGES OldState;
1502 ULONG ReturnLength;
1503 HANDLE TokenHandle;
1504 NTSTATUS Status;
1506 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1507 CurrentThread ? "TRUE" : "FALSE", Enabled);
1509 if (CurrentThread)
1511 Status = NtOpenThreadToken(GetCurrentThread(),
1512 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1513 FALSE,
1514 &TokenHandle);
1516 else
1518 Status = NtOpenProcessToken(GetCurrentProcess(),
1519 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1520 &TokenHandle);
1523 if (!NT_SUCCESS(Status))
1525 WARN("Retrieving token handle failed (Status %x)\n", Status);
1526 return Status;
1529 OldState.PrivilegeCount = 1;
1531 NewState.PrivilegeCount = 1;
1532 NewState.Privileges[0].Luid.LowPart = Privilege;
1533 NewState.Privileges[0].Luid.HighPart = 0;
1534 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1536 Status = NtAdjustPrivilegesToken(TokenHandle,
1537 FALSE,
1538 &NewState,
1539 sizeof(TOKEN_PRIVILEGES),
1540 &OldState,
1541 &ReturnLength);
1542 NtClose (TokenHandle);
1543 if (Status == STATUS_NOT_ALL_ASSIGNED)
1545 TRACE("Failed to assign all privileges\n");
1546 return STATUS_PRIVILEGE_NOT_HELD;
1548 if (!NT_SUCCESS(Status))
1550 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1551 return Status;
1554 if (OldState.PrivilegeCount == 0)
1555 *Enabled = Enable;
1556 else
1557 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1559 return STATUS_SUCCESS;
1562 /******************************************************************************
1563 * RtlImpersonateSelf [NTDLL.@]
1565 * Makes an impersonation token that represents the process user and assigns
1566 * to the current thread.
1568 * PARAMS
1569 * ImpersonationLevel [I] Level at which to impersonate.
1571 * RETURNS
1572 * Success: STATUS_SUCCESS.
1573 * Failure: NTSTATUS code.
1575 NTSTATUS WINAPI
1576 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1578 NTSTATUS Status;
1579 OBJECT_ATTRIBUTES ObjectAttributes;
1580 HANDLE ProcessToken;
1581 HANDLE ImpersonationToken;
1583 TRACE("(%08x)\n", ImpersonationLevel);
1585 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1586 &ProcessToken);
1587 if (Status != STATUS_SUCCESS)
1588 return Status;
1590 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1592 Status = NtDuplicateToken( ProcessToken,
1593 TOKEN_IMPERSONATE,
1594 &ObjectAttributes,
1595 ImpersonationLevel,
1596 TokenImpersonation,
1597 &ImpersonationToken );
1598 if (Status != STATUS_SUCCESS)
1600 NtClose( ProcessToken );
1601 return Status;
1604 Status = NtSetInformationThread( GetCurrentThread(),
1605 ThreadImpersonationToken,
1606 &ImpersonationToken,
1607 sizeof(ImpersonationToken) );
1609 NtClose( ImpersonationToken );
1610 NtClose( ProcessToken );
1612 return Status;
1615 /******************************************************************************
1616 * NtImpersonateAnonymousToken [NTDLL.@]
1618 NTSTATUS WINAPI
1619 NtImpersonateAnonymousToken(HANDLE thread)
1621 FIXME("(%p): stub\n", thread);
1622 return STATUS_NOT_IMPLEMENTED;
1625 /******************************************************************************
1626 * NtAccessCheck [NTDLL.@]
1627 * ZwAccessCheck [NTDLL.@]
1629 * Checks that a user represented by a token is allowed to access an object
1630 * represented by a security descriptor.
1632 * PARAMS
1633 * SecurityDescriptor [I] The security descriptor of the object to check.
1634 * ClientToken [I] Token of the user accessing the object.
1635 * DesiredAccess [I] The desired access to the object.
1636 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1637 * PrivilegeSet [I/O] Privileges used during the access check.
1638 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1639 * GrantedAccess [O] The actual access rights granted.
1640 * AccessStatus [O] The status of the access check.
1642 * RETURNS
1643 * NTSTATUS code.
1645 * NOTES
1646 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1647 * the maximum access rights allowed by the SD and returns them in
1648 * GrantedAccess.
1649 * The SecurityDescriptor must have a valid owner and groups present,
1650 * otherwise the function will fail.
1652 NTSTATUS WINAPI
1653 NtAccessCheck(
1654 PSECURITY_DESCRIPTOR SecurityDescriptor,
1655 HANDLE ClientToken,
1656 ACCESS_MASK DesiredAccess,
1657 PGENERIC_MAPPING GenericMapping,
1658 PPRIVILEGE_SET PrivilegeSet,
1659 PULONG ReturnLength,
1660 PULONG GrantedAccess,
1661 NTSTATUS *AccessStatus)
1663 NTSTATUS status;
1665 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1666 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1667 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1669 if (!PrivilegeSet || !ReturnLength)
1670 return STATUS_ACCESS_VIOLATION;
1672 SERVER_START_REQ( access_check )
1674 struct security_descriptor sd;
1675 PSID owner;
1676 PSID group;
1677 PACL sacl;
1678 PACL dacl;
1679 BOOLEAN defaulted, present;
1680 DWORD revision;
1681 SECURITY_DESCRIPTOR_CONTROL control;
1683 req->handle = wine_server_obj_handle( ClientToken );
1684 req->desired_access = DesiredAccess;
1685 req->mapping_read = GenericMapping->GenericRead;
1686 req->mapping_write = GenericMapping->GenericWrite;
1687 req->mapping_execute = GenericMapping->GenericExecute;
1688 req->mapping_all = GenericMapping->GenericAll;
1690 /* marshal security descriptor */
1691 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1692 sd.control = control & ~SE_SELF_RELATIVE;
1693 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1694 sd.owner_len = RtlLengthSid( owner );
1695 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1696 sd.group_len = RtlLengthSid( group );
1697 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1698 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1699 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1700 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1702 wine_server_add_data( req, &sd, sizeof(sd) );
1703 wine_server_add_data( req, owner, sd.owner_len );
1704 wine_server_add_data( req, group, sd.group_len );
1705 wine_server_add_data( req, sacl, sd.sacl_len );
1706 wine_server_add_data( req, dacl, sd.dacl_len );
1708 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1710 status = wine_server_call( req );
1712 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1713 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1715 if (status == STATUS_SUCCESS)
1717 *AccessStatus = reply->access_status;
1718 *GrantedAccess = reply->access_granted;
1721 SERVER_END_REQ;
1723 return status;
1726 /******************************************************************************
1727 * NtSetSecurityObject [NTDLL.@]
1728 * ZwSetSecurityObject [NTDLL.@]
1730 * Sets specified parts of the object's security descriptor.
1732 * PARAMS
1733 * Handle [I] Handle to the object to change security descriptor of.
1734 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1735 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1737 * RETURNS
1738 * NTSTATUS code.
1741 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1742 SECURITY_INFORMATION SecurityInformation,
1743 PSECURITY_DESCRIPTOR SecurityDescriptor)
1745 NTSTATUS status;
1746 struct security_descriptor sd;
1747 PACL dacl = NULL, sacl = NULL;
1748 PSID owner = NULL, group = NULL;
1749 BOOLEAN defaulted, present;
1750 DWORD revision;
1751 SECURITY_DESCRIPTOR_CONTROL control;
1753 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1755 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1757 memset( &sd, 0, sizeof(sd) );
1758 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1759 if (status != STATUS_SUCCESS) return status;
1760 sd.control = control & ~SE_SELF_RELATIVE;
1762 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1764 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1765 if (status != STATUS_SUCCESS) return status;
1766 if (!(sd.owner_len = RtlLengthSid( owner )))
1767 return STATUS_INVALID_SECURITY_DESCR;
1770 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1772 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1773 if (status != STATUS_SUCCESS) return status;
1774 if (!(sd.group_len = RtlLengthSid( group )))
1775 return STATUS_INVALID_SECURITY_DESCR;
1778 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1780 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1781 if (status != STATUS_SUCCESS) return status;
1782 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1783 sd.control |= SE_SACL_PRESENT;
1786 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1788 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1789 if (status != STATUS_SUCCESS) return status;
1790 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1791 sd.control |= SE_DACL_PRESENT;
1794 SERVER_START_REQ( set_security_object )
1796 req->handle = wine_server_obj_handle( Handle );
1797 req->security_info = SecurityInformation;
1799 wine_server_add_data( req, &sd, sizeof(sd) );
1800 wine_server_add_data( req, owner, sd.owner_len );
1801 wine_server_add_data( req, group, sd.group_len );
1802 wine_server_add_data( req, sacl, sd.sacl_len );
1803 wine_server_add_data( req, dacl, sd.dacl_len );
1804 status = wine_server_call( req );
1806 SERVER_END_REQ;
1808 return status;
1811 /******************************************************************************
1812 * RtlConvertSidToUnicodeString (NTDLL.@)
1814 * The returned SID is used to access the USER registry hive usually
1816 * the native function returns something like
1817 * "S-1-5-21-0000000000-000000000-0000000000-500";
1819 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1820 PUNICODE_STRING String,
1821 PSID pSid,
1822 BOOLEAN AllocateString)
1824 static const WCHAR formatW[] = {'-','%','u',0};
1825 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1826 WCHAR *p = buffer;
1827 const SID *sid = pSid;
1828 DWORD i, len;
1830 *p++ = 'S';
1831 p += sprintfW( p, formatW, sid->Revision );
1832 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1833 sid->IdentifierAuthority.Value[4] ),
1834 MAKEWORD( sid->IdentifierAuthority.Value[3],
1835 sid->IdentifierAuthority.Value[2] )));
1836 for (i = 0; i < sid->SubAuthorityCount; i++)
1837 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1839 len = (p + 1 - buffer) * sizeof(WCHAR);
1841 String->Length = len - sizeof(WCHAR);
1842 if (AllocateString)
1844 String->MaximumLength = len;
1845 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1846 return STATUS_NO_MEMORY;
1848 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1850 memcpy( String->Buffer, buffer, len );
1851 return STATUS_SUCCESS;
1854 /******************************************************************************
1855 * RtlQueryInformationAcl (NTDLL.@)
1857 NTSTATUS WINAPI RtlQueryInformationAcl(
1858 PACL pAcl,
1859 LPVOID pAclInformation,
1860 DWORD nAclInformationLength,
1861 ACL_INFORMATION_CLASS dwAclInformationClass)
1863 NTSTATUS status = STATUS_SUCCESS;
1865 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1866 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1868 switch (dwAclInformationClass)
1870 case AclRevisionInformation:
1872 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1874 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1875 status = STATUS_INVALID_PARAMETER;
1876 else
1877 paclrev->AclRevision = pAcl->AclRevision;
1879 break;
1882 case AclSizeInformation:
1884 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1886 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1887 status = STATUS_INVALID_PARAMETER;
1888 else
1890 paclsize->AceCount = pAcl->AceCount;
1891 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1892 if (pAcl->AclSize < paclsize->AclBytesInUse)
1894 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1895 paclsize->AclBytesFree = 0;
1896 paclsize->AclBytesInUse = pAcl->AclSize;
1898 else
1899 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1902 break;
1905 default:
1906 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1907 status = STATUS_INVALID_PARAMETER;
1910 return status;
1913 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1914 PSECURITY_DESCRIPTOR pdesc,
1915 PSECURITY_DESCRIPTOR cdesc,
1916 PSECURITY_DESCRIPTOR* ndesc,
1917 GUID* objtype,
1918 BOOL isdir,
1919 PGENERIC_MAPPING genmap )
1921 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1923 return FALSE;