server: Fix connect failures on newer kernels.
[wine.git] / dlls / ntdll / sec.c
blob6784848de30f274799b62cb1779bf133bb8fab2c
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 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
170 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
171 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
172 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
173 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
174 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
175 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
176 break;
178 *pSid = tmp_sid;
179 return STATUS_SUCCESS;
182 /******************************************************************************
183 * RtlEqualSid [NTDLL.@]
185 * Determine if two SIDs are equal.
187 * PARAMS
188 * pSid1 [I] Source SID
189 * pSid2 [I] SID to compare with
191 * RETURNS
192 * TRUE, if pSid1 is equal to pSid2,
193 * FALSE otherwise.
195 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
197 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
198 return FALSE;
200 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
201 return FALSE;
203 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
204 return FALSE;
206 return TRUE;
209 /******************************************************************************
210 * RtlEqualPrefixSid [NTDLL.@]
212 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
214 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
215 return FALSE;
217 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
218 return FALSE;
220 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
221 return FALSE;
223 return TRUE;
227 /******************************************************************************
228 * RtlFreeSid [NTDLL.@]
230 * Free the resources used by a SID.
232 * PARAMS
233 * pSid [I] SID to Free.
235 * RETURNS
236 * STATUS_SUCCESS.
238 DWORD WINAPI RtlFreeSid(PSID pSid)
240 TRACE("(%p)\n", pSid);
241 RtlFreeHeap( GetProcessHeap(), 0, pSid );
242 return STATUS_SUCCESS;
245 /**************************************************************************
246 * RtlLengthRequiredSid [NTDLL.@]
248 * Determine the amount of memory a SID will use
250 * PARAMS
251 * nrofsubauths [I] Number of Sub Authorities in the SID.
253 * RETURNS
254 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
256 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
258 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
261 /**************************************************************************
262 * RtlLengthSid [NTDLL.@]
264 * Determine the amount of memory a SID is using
266 * PARAMS
267 * pSid [I] SID to get the size of.
269 * RETURNS
270 * The size, in bytes, of pSid.
272 DWORD WINAPI RtlLengthSid(PSID pSid)
274 TRACE("sid=%p\n",pSid);
275 if (!pSid) return 0;
276 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
279 /**************************************************************************
280 * RtlInitializeSid [NTDLL.@]
282 * Initialise a SID.
284 * PARAMS
285 * pSid [I] SID to initialise
286 * pIdentifierAuthority [I] Identifier Authority
287 * nSubAuthorityCount [I] Number of Sub Authorities
289 * RETURNS
290 * Success: TRUE. pSid is initialised with the details given.
291 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
293 BOOL WINAPI RtlInitializeSid(
294 PSID pSid,
295 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
296 BYTE nSubAuthorityCount)
298 int i;
299 SID* pisid=pSid;
301 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
302 return FALSE;
304 pisid->Revision = SID_REVISION;
305 pisid->SubAuthorityCount = nSubAuthorityCount;
306 if (pIdentifierAuthority)
307 pisid->IdentifierAuthority = *pIdentifierAuthority;
309 for (i = 0; i < nSubAuthorityCount; i++)
310 *RtlSubAuthoritySid(pSid, i) = 0;
312 return TRUE;
315 /**************************************************************************
316 * RtlSubAuthoritySid [NTDLL.@]
318 * Return the Sub Authority of a SID
320 * PARAMS
321 * pSid [I] SID to get the Sub Authority from.
322 * nSubAuthority [I] Sub Authority number.
324 * RETURNS
325 * A pointer to The Sub Authority value of pSid.
327 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
329 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
332 /**************************************************************************
333 * RtlIdentifierAuthoritySid [NTDLL.@]
335 * Return the Identifier Authority of a SID.
337 * PARAMS
338 * pSid [I] SID to get the Identifier Authority from.
340 * RETURNS
341 * A pointer to the Identifier Authority value of pSid.
343 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
345 return &(((SID*)pSid)->IdentifierAuthority);
348 /**************************************************************************
349 * RtlSubAuthorityCountSid [NTDLL.@]
351 * Get the number of Sub Authorities in a SID.
353 * PARAMS
354 * pSid [I] SID to get the count from.
356 * RETURNS
357 * A pointer to the Sub Authority count of pSid.
359 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
361 return &(((SID*)pSid)->SubAuthorityCount);
364 /**************************************************************************
365 * RtlCopySid [NTDLL.@]
367 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
369 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
370 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
371 return FALSE;
373 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
374 return FALSE;
376 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
377 return TRUE;
379 /******************************************************************************
380 * RtlValidSid [NTDLL.@]
382 * Determine if a SID is valid.
384 * PARAMS
385 * pSid [I] SID to check
387 * RETURNS
388 * TRUE if pSid is valid,
389 * FALSE otherwise.
391 BOOLEAN WINAPI RtlValidSid( PSID pSid )
393 BOOL ret;
394 __TRY
396 ret = TRUE;
397 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
398 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
400 ret = FALSE;
403 __EXCEPT_PAGE_FAULT
405 WARN("(%p): invalid pointer!\n", pSid);
406 return FALSE;
408 __ENDTRY
409 return ret;
414 * security descriptor functions
417 /**************************************************************************
418 * RtlCreateSecurityDescriptor [NTDLL.@]
420 * Initialise a SECURITY_DESCRIPTOR.
422 * PARAMS
423 * lpsd [O] Descriptor to initialise.
424 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
426 * RETURNS
427 * Success: STATUS_SUCCESS.
428 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
430 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
431 PSECURITY_DESCRIPTOR lpsd,
432 DWORD rev)
434 if (rev!=SECURITY_DESCRIPTOR_REVISION)
435 return STATUS_UNKNOWN_REVISION;
436 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
437 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
438 return STATUS_SUCCESS;
441 /**************************************************************************
442 * RtlCopySecurityDescriptor [NTDLL.@]
444 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
446 * PARAMS
447 * pSourceSD [O] SD to copy from.
448 * pDestinationSD [I] Destination SD.
450 * RETURNS
451 * Success: STATUS_SUCCESS.
452 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
454 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
456 PSID Owner, Group;
457 PACL Dacl, Sacl;
458 DWORD length;
460 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
462 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
463 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
465 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
466 return STATUS_UNKNOWN_REVISION;
468 *dst = *src;
469 if (src->Owner)
471 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
472 length = RtlLengthSid( Owner );
473 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
475 if (src->Group)
477 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
478 length = RtlLengthSid( Group );
479 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
481 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
483 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
484 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
486 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
488 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
489 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
492 else
494 SECURITY_DESCRIPTOR *src = pSourceSD;
495 SECURITY_DESCRIPTOR *dst = pDestinationSD;
497 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
498 return STATUS_UNKNOWN_REVISION;
500 *dst = *src;
501 if (src->Owner)
503 length = RtlLengthSid( src->Owner );
504 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
505 RtlCopySid(length, dst->Owner, src->Owner);
507 if (src->Group)
509 length = RtlLengthSid( src->Group );
510 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
511 RtlCopySid(length, dst->Group, src->Group);
513 if (src->Control & SE_SACL_PRESENT)
515 length = src->Sacl->AclSize;
516 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
517 copy_acl(length, dst->Sacl, src->Sacl);
519 if (src->Control & SE_DACL_PRESENT)
521 length = src->Dacl->AclSize;
522 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
523 copy_acl(length, dst->Dacl, src->Dacl);
527 return STATUS_SUCCESS;
530 /**************************************************************************
531 * RtlValidSecurityDescriptor [NTDLL.@]
533 * Determine if a SECURITY_DESCRIPTOR is valid.
535 * PARAMS
536 * SecurityDescriptor [I] Descriptor to check.
538 * RETURNS
539 * Success: STATUS_SUCCESS.
540 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
542 NTSTATUS WINAPI RtlValidSecurityDescriptor(
543 PSECURITY_DESCRIPTOR SecurityDescriptor)
545 if ( ! SecurityDescriptor )
546 return STATUS_INVALID_SECURITY_DESCR;
547 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
548 return STATUS_UNKNOWN_REVISION;
550 return STATUS_SUCCESS;
553 /**************************************************************************
554 * RtlLengthSecurityDescriptor [NTDLL.@]
556 ULONG WINAPI RtlLengthSecurityDescriptor(
557 PSECURITY_DESCRIPTOR pSecurityDescriptor)
559 ULONG size;
561 if ( pSecurityDescriptor == NULL )
562 return 0;
564 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
566 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
567 size = sizeof(*sd);
568 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
569 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
570 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
571 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
572 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
573 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
575 else
577 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
578 size = sizeof(*sd);
579 if (sd->Owner) size += RtlLengthSid( sd->Owner );
580 if (sd->Group) size += RtlLengthSid( sd->Group );
581 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
582 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
584 return size;
587 /******************************************************************************
588 * RtlGetDaclSecurityDescriptor [NTDLL.@]
591 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
592 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
593 OUT PBOOLEAN lpbDaclPresent,
594 OUT PACL *pDacl,
595 OUT PBOOLEAN lpbDaclDefaulted)
597 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
599 TRACE("(%p,%p,%p,%p)\n",
600 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
602 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
603 return STATUS_UNKNOWN_REVISION ;
605 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
607 if ((SE_SELF_RELATIVE & lpsd->Control) && lpsd->Dacl)
608 *pDacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Dacl );
609 else
610 *pDacl = lpsd->Dacl;
612 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
614 else
616 *pDacl = NULL;
617 *lpbDaclDefaulted = 0;
620 return STATUS_SUCCESS;
623 /**************************************************************************
624 * RtlSetDaclSecurityDescriptor [NTDLL.@]
626 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
627 PSECURITY_DESCRIPTOR pSecurityDescriptor,
628 BOOLEAN daclpresent,
629 PACL dacl,
630 BOOLEAN dacldefaulted )
632 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
634 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
635 return STATUS_UNKNOWN_REVISION;
636 if (lpsd->Control & SE_SELF_RELATIVE)
637 return STATUS_INVALID_SECURITY_DESCR;
639 if (!daclpresent)
641 lpsd->Control &= ~SE_DACL_PRESENT;
642 return STATUS_SUCCESS;
645 lpsd->Control |= SE_DACL_PRESENT;
646 lpsd->Dacl = dacl;
648 if (dacldefaulted)
649 lpsd->Control |= SE_DACL_DEFAULTED;
650 else
651 lpsd->Control &= ~SE_DACL_DEFAULTED;
653 return STATUS_SUCCESS;
656 /******************************************************************************
657 * RtlGetSaclSecurityDescriptor [NTDLL.@]
660 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
661 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
662 OUT PBOOLEAN lpbSaclPresent,
663 OUT PACL *pSacl,
664 OUT PBOOLEAN lpbSaclDefaulted)
666 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
668 TRACE("(%p,%p,%p,%p)\n",
669 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
671 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
672 return STATUS_UNKNOWN_REVISION;
674 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
676 if ((SE_SELF_RELATIVE & lpsd->Control) && lpsd->Sacl)
677 *pSacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Sacl );
678 else
679 *pSacl = lpsd->Sacl;
681 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
683 return STATUS_SUCCESS;
686 /**************************************************************************
687 * RtlSetSaclSecurityDescriptor [NTDLL.@]
689 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
690 PSECURITY_DESCRIPTOR pSecurityDescriptor,
691 BOOLEAN saclpresent,
692 PACL sacl,
693 BOOLEAN sacldefaulted)
695 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
697 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
698 return STATUS_UNKNOWN_REVISION;
699 if (lpsd->Control & SE_SELF_RELATIVE)
700 return STATUS_INVALID_SECURITY_DESCR;
701 if (!saclpresent) {
702 lpsd->Control &= ~SE_SACL_PRESENT;
703 return 0;
705 lpsd->Control |= SE_SACL_PRESENT;
706 lpsd->Sacl = sacl;
707 if (sacldefaulted)
708 lpsd->Control |= SE_SACL_DEFAULTED;
709 else
710 lpsd->Control &= ~SE_SACL_DEFAULTED;
711 return STATUS_SUCCESS;
714 /**************************************************************************
715 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
717 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
718 PSECURITY_DESCRIPTOR pSecurityDescriptor,
719 PSID *Owner,
720 PBOOLEAN OwnerDefaulted)
722 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
724 if ( !lpsd || !Owner || !OwnerDefaulted )
725 return STATUS_INVALID_PARAMETER;
727 if ( lpsd->Control & SE_OWNER_DEFAULTED )
728 *OwnerDefaulted = TRUE;
729 else
730 *OwnerDefaulted = FALSE;
732 if (lpsd->Control & SE_SELF_RELATIVE)
734 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
735 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
736 else *Owner = NULL;
738 else
739 *Owner = lpsd->Owner;
741 return STATUS_SUCCESS;
744 /**************************************************************************
745 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
747 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
748 PSECURITY_DESCRIPTOR pSecurityDescriptor,
749 PSID owner,
750 BOOLEAN ownerdefaulted)
752 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
754 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
755 return STATUS_UNKNOWN_REVISION;
756 if (lpsd->Control & SE_SELF_RELATIVE)
757 return STATUS_INVALID_SECURITY_DESCR;
759 lpsd->Owner = owner;
760 if (ownerdefaulted)
761 lpsd->Control |= SE_OWNER_DEFAULTED;
762 else
763 lpsd->Control &= ~SE_OWNER_DEFAULTED;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetGroupSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
772 PSID group,
773 BOOLEAN groupdefaulted)
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->Group = group;
783 if (groupdefaulted)
784 lpsd->Control |= SE_GROUP_DEFAULTED;
785 else
786 lpsd->Control &= ~SE_GROUP_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlGetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
795 PSID *Group,
796 PBOOLEAN GroupDefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if ( !lpsd || !Group || !GroupDefaulted )
801 return STATUS_INVALID_PARAMETER;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
805 else
806 *GroupDefaulted = FALSE;
808 if (lpsd->Control & SE_SELF_RELATIVE)
810 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
811 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
812 else *Group = NULL;
814 else
815 *Group = lpsd->Group;
817 return STATUS_SUCCESS;
820 /**************************************************************************
821 * RtlMakeSelfRelativeSD [NTDLL.@]
823 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
824 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
825 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
826 IN OUT LPDWORD lpdwBufferLength)
828 DWORD offsetRel;
829 ULONG length;
830 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
831 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
833 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
834 lpdwBufferLength ? *lpdwBufferLength: -1);
836 if (!lpdwBufferLength || !pAbs)
837 return STATUS_INVALID_PARAMETER;
839 length = RtlLengthSecurityDescriptor(pAbs);
840 if (*lpdwBufferLength < length)
842 *lpdwBufferLength = length;
843 return STATUS_BUFFER_TOO_SMALL;
846 if (!pRel)
847 return STATUS_INVALID_PARAMETER;
849 if (pAbs->Control & SE_SELF_RELATIVE)
851 memcpy(pRel, pAbs, length);
852 return STATUS_SUCCESS;
855 pRel->Revision = pAbs->Revision;
856 pRel->Sbz1 = pAbs->Sbz1;
857 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
859 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
860 if (pAbs->Owner)
862 pRel->Owner = offsetRel;
863 length = RtlLengthSid(pAbs->Owner);
864 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
865 offsetRel += length;
867 else
869 pRel->Owner = 0;
872 if (pAbs->Group)
874 pRel->Group = offsetRel;
875 length = RtlLengthSid(pAbs->Group);
876 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
877 offsetRel += length;
879 else
881 pRel->Group = 0;
884 if (pAbs->Sacl)
886 pRel->Sacl = offsetRel;
887 length = pAbs->Sacl->AclSize;
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
889 offsetRel += length;
891 else
893 pRel->Sacl = 0;
896 if (pAbs->Dacl)
898 pRel->Dacl = offsetRel;
899 length = pAbs->Dacl->AclSize;
900 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
902 else
904 pRel->Dacl = 0;
907 return STATUS_SUCCESS;
911 /**************************************************************************
912 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
914 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
915 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
916 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
917 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
918 OUT PACL pDacl,
919 OUT LPDWORD lpdwDaclSize,
920 OUT PACL pSacl,
921 OUT LPDWORD lpdwSaclSize,
922 OUT PSID pOwner,
923 OUT LPDWORD lpdwOwnerSize,
924 OUT PSID pPrimaryGroup,
925 OUT LPDWORD lpdwPrimaryGroupSize)
927 NTSTATUS status = STATUS_SUCCESS;
928 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
929 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
931 if (!pRel ||
932 !lpdwAbsoluteSecurityDescriptorSize ||
933 !lpdwDaclSize ||
934 !lpdwSaclSize ||
935 !lpdwOwnerSize ||
936 !lpdwPrimaryGroupSize ||
937 ~pRel->Control & SE_SELF_RELATIVE)
938 return STATUS_INVALID_PARAMETER;
940 /* Confirm buffers are sufficiently large */
941 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
943 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
944 status = STATUS_BUFFER_TOO_SMALL;
947 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
948 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
950 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
951 status = STATUS_BUFFER_TOO_SMALL;
954 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
955 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
957 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (pRel->Owner &&
962 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
964 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
965 status = STATUS_BUFFER_TOO_SMALL;
968 if (pRel->Group &&
969 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
971 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (status != STATUS_SUCCESS)
976 return status;
978 /* Copy structures, and clear the ones we don't set */
979 pAbs->Revision = pRel->Revision;
980 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
981 pAbs->Sacl = NULL;
982 pAbs->Dacl = NULL;
983 pAbs->Owner = NULL;
984 pAbs->Group = NULL;
986 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
988 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
990 memcpy(pSacl, pAcl, pAcl->AclSize);
991 pAbs->Sacl = pSacl;
994 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
996 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
997 memcpy(pDacl, pAcl, pAcl->AclSize);
998 pAbs->Dacl = pDacl;
1001 if (pRel->Owner)
1003 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1004 memcpy(pOwner, psid, RtlLengthSid(psid));
1005 pAbs->Owner = pOwner;
1008 if (pRel->Group)
1010 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1011 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1012 pAbs->Group = pPrimaryGroup;
1015 return status;
1018 /******************************************************************************
1019 * RtlGetControlSecurityDescriptor (NTDLL.@)
1021 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1022 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1023 PSECURITY_DESCRIPTOR_CONTROL pControl,
1024 LPDWORD lpdwRevision)
1026 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1028 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1030 *lpdwRevision = lpsd->Revision;
1032 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1033 return STATUS_UNKNOWN_REVISION;
1035 *pControl = lpsd->Control;
1037 return STATUS_SUCCESS;
1040 /******************************************************************************
1041 * RtlSetControlSecurityDescriptor (NTDLL.@)
1043 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1044 PSECURITY_DESCRIPTOR SecurityDescriptor,
1045 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1046 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1048 SECURITY_DESCRIPTOR_CONTROL const immutable
1049 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1050 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1051 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1052 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1055 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1057 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1058 ControlBitsOfInterest, ControlBitsToSet);
1060 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1061 return STATUS_INVALID_PARAMETER;
1063 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1064 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1066 return STATUS_SUCCESS;
1070 /**************************************************************************
1071 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1073 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1074 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1075 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1076 PULONG BufferLength)
1078 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1080 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1081 SelfRelativeSecurityDescriptor, BufferLength);
1083 if (abs->Control & SE_SELF_RELATIVE)
1084 return STATUS_BAD_DESCRIPTOR_FORMAT;
1086 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1087 SelfRelativeSecurityDescriptor, BufferLength);
1092 * access control list's
1095 /**************************************************************************
1096 * RtlCreateAcl [NTDLL.@]
1098 * NOTES
1099 * This should return NTSTATUS
1101 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1103 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1105 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1106 return STATUS_INVALID_PARAMETER;
1107 if (size<sizeof(ACL))
1108 return STATUS_BUFFER_TOO_SMALL;
1109 if (size>0xFFFF)
1110 return STATUS_INVALID_PARAMETER;
1112 memset(acl,'\0',sizeof(ACL));
1113 acl->AclRevision = rev;
1114 acl->AclSize = size;
1115 acl->AceCount = 0;
1116 return STATUS_SUCCESS;
1119 /**************************************************************************
1120 * RtlFirstFreeAce [NTDLL.@]
1121 * looks for the AceCount+1 ACE, and if it is still within the alloced
1122 * ACL, return a pointer to it
1124 BOOLEAN WINAPI RtlFirstFreeAce(
1125 PACL acl,
1126 PACE_HEADER *x)
1128 PACE_HEADER ace;
1129 int i;
1131 *x = 0;
1132 ace = (PACE_HEADER)(acl+1);
1133 for (i=0;i<acl->AceCount;i++) {
1134 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1135 return 0;
1136 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1138 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1139 return 0;
1140 *x = ace;
1141 return 1;
1144 /**************************************************************************
1145 * RtlAddAce [NTDLL.@]
1147 NTSTATUS WINAPI RtlAddAce(
1148 PACL acl,
1149 DWORD rev,
1150 DWORD xnrofaces,
1151 PACE_HEADER acestart,
1152 DWORD acelen)
1154 PACE_HEADER ace,targetace;
1155 int nrofaces;
1157 if (acl->AclRevision != ACL_REVISION)
1158 return STATUS_INVALID_PARAMETER;
1159 if (!RtlFirstFreeAce(acl,&targetace))
1160 return STATUS_INVALID_PARAMETER;
1161 nrofaces=0;ace=acestart;
1162 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1163 nrofaces++;
1164 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1166 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1167 return STATUS_INVALID_PARAMETER;
1168 memcpy(targetace,acestart,acelen);
1169 acl->AceCount+=nrofaces;
1170 return STATUS_SUCCESS;
1173 /**************************************************************************
1174 * RtlDeleteAce [NTDLL.@]
1176 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1178 NTSTATUS status;
1179 PACE_HEADER pAce;
1181 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1183 if (STATUS_SUCCESS == status)
1185 PACE_HEADER pcAce;
1186 DWORD len = 0;
1188 /* skip over the ACE we are deleting */
1189 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1190 dwAceIndex++;
1192 /* calculate the length of the rest */
1193 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1195 len += pcAce->AceSize;
1196 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1199 /* slide them all backwards */
1200 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1201 pAcl->AceCount--;
1204 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1206 return status;
1209 /******************************************************************************
1210 * RtlAddAccessAllowedAce [NTDLL.@]
1212 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1213 IN OUT PACL pAcl,
1214 IN DWORD dwAceRevision,
1215 IN DWORD AccessMask,
1216 IN PSID pSid)
1218 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1221 /******************************************************************************
1222 * RtlAddAccessAllowedAceEx [NTDLL.@]
1224 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1225 IN OUT PACL pAcl,
1226 IN DWORD dwAceRevision,
1227 IN DWORD AceFlags,
1228 IN DWORD AccessMask,
1229 IN PSID pSid)
1231 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1233 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1234 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1237 /******************************************************************************
1238 * RtlAddAccessDeniedAce [NTDLL.@]
1240 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1241 IN OUT PACL pAcl,
1242 IN DWORD dwAceRevision,
1243 IN DWORD AccessMask,
1244 IN PSID pSid)
1246 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1249 /******************************************************************************
1250 * RtlAddAccessDeniedAceEx [NTDLL.@]
1252 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1253 IN OUT PACL pAcl,
1254 IN DWORD dwAceRevision,
1255 IN DWORD AceFlags,
1256 IN DWORD AccessMask,
1257 IN PSID pSid)
1259 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1261 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1262 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1265 /**************************************************************************
1266 * RtlAddAuditAccessAce [NTDLL.@]
1268 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1269 IN OUT PACL pAcl,
1270 IN DWORD dwAceRevision,
1271 IN DWORD dwAceFlags,
1272 IN DWORD dwAccessMask,
1273 IN PSID pSid,
1274 IN BOOL bAuditSuccess,
1275 IN BOOL bAuditFailure)
1277 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1278 pSid,bAuditSuccess,bAuditFailure);
1280 if (bAuditSuccess)
1281 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1283 if (bAuditFailure)
1284 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1286 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1287 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1290 /**************************************************************************
1291 * RtlAddAuditAccessAce [NTDLL.@]
1293 NTSTATUS WINAPI RtlAddAuditAccessAce(
1294 IN OUT PACL pAcl,
1295 IN DWORD dwAceRevision,
1296 IN DWORD dwAccessMask,
1297 IN PSID pSid,
1298 IN BOOL bAuditSuccess,
1299 IN BOOL bAuditFailure)
1301 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1304 /******************************************************************************
1305 * RtlValidAcl [NTDLL.@]
1307 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1309 BOOLEAN ret;
1310 TRACE("(%p)\n", pAcl);
1312 __TRY
1314 PACE_HEADER ace;
1315 int i;
1317 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1318 pAcl->AclRevision > MAX_ACL_REVISION)
1319 ret = FALSE;
1320 else
1322 ace = (PACE_HEADER)(pAcl+1);
1323 ret = TRUE;
1324 for (i=0;i<=pAcl->AceCount;i++)
1326 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1328 ret = FALSE;
1329 break;
1331 if (i != pAcl->AceCount)
1332 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1336 __EXCEPT_PAGE_FAULT
1338 WARN("(%p): invalid pointer!\n", pAcl);
1339 return 0;
1341 __ENDTRY
1342 return ret;
1345 /******************************************************************************
1346 * RtlGetAce [NTDLL.@]
1348 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1350 PACE_HEADER ace;
1352 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1354 if (dwAceIndex >= pAcl->AceCount)
1355 return STATUS_INVALID_PARAMETER;
1357 ace = (PACE_HEADER)(pAcl + 1);
1358 for (;dwAceIndex;dwAceIndex--)
1359 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1361 *pAce = ace;
1363 return STATUS_SUCCESS;
1367 * misc
1370 /******************************************************************************
1371 * RtlAdjustPrivilege [NTDLL.@]
1373 * Enables or disables a privilege from the calling thread or process.
1375 * PARAMS
1376 * Privilege [I] Privilege index to change.
1377 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1378 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1379 * Enabled [O] Whether privilege was previously enabled or disabled.
1381 * RETURNS
1382 * Success: STATUS_SUCCESS.
1383 * Failure: NTSTATUS code.
1385 * SEE ALSO
1386 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1389 NTSTATUS WINAPI
1390 RtlAdjustPrivilege(ULONG Privilege,
1391 BOOLEAN Enable,
1392 BOOLEAN CurrentThread,
1393 PBOOLEAN Enabled)
1395 TOKEN_PRIVILEGES NewState;
1396 TOKEN_PRIVILEGES OldState;
1397 ULONG ReturnLength;
1398 HANDLE TokenHandle;
1399 NTSTATUS Status;
1401 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1402 CurrentThread ? "TRUE" : "FALSE", Enabled);
1404 if (CurrentThread)
1406 Status = NtOpenThreadToken(GetCurrentThread(),
1407 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1408 FALSE,
1409 &TokenHandle);
1411 else
1413 Status = NtOpenProcessToken(GetCurrentProcess(),
1414 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1415 &TokenHandle);
1418 if (!NT_SUCCESS(Status))
1420 WARN("Retrieving token handle failed (Status %x)\n", Status);
1421 return Status;
1424 OldState.PrivilegeCount = 1;
1426 NewState.PrivilegeCount = 1;
1427 NewState.Privileges[0].Luid.LowPart = Privilege;
1428 NewState.Privileges[0].Luid.HighPart = 0;
1429 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1431 Status = NtAdjustPrivilegesToken(TokenHandle,
1432 FALSE,
1433 &NewState,
1434 sizeof(TOKEN_PRIVILEGES),
1435 &OldState,
1436 &ReturnLength);
1437 NtClose (TokenHandle);
1438 if (Status == STATUS_NOT_ALL_ASSIGNED)
1440 TRACE("Failed to assign all privileges\n");
1441 return STATUS_PRIVILEGE_NOT_HELD;
1443 if (!NT_SUCCESS(Status))
1445 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1446 return Status;
1449 if (OldState.PrivilegeCount == 0)
1450 *Enabled = Enable;
1451 else
1452 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1454 return STATUS_SUCCESS;
1457 /******************************************************************************
1458 * RtlImpersonateSelf [NTDLL.@]
1460 * Makes an impersonation token that represents the process user and assigns
1461 * to the current thread.
1463 * PARAMS
1464 * ImpersonationLevel [I] Level at which to impersonate.
1466 * RETURNS
1467 * Success: STATUS_SUCCESS.
1468 * Failure: NTSTATUS code.
1470 NTSTATUS WINAPI
1471 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1473 NTSTATUS Status;
1474 OBJECT_ATTRIBUTES ObjectAttributes;
1475 HANDLE ProcessToken;
1476 HANDLE ImpersonationToken;
1478 TRACE("(%08x)\n", ImpersonationLevel);
1480 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1481 &ProcessToken);
1482 if (Status != STATUS_SUCCESS)
1483 return Status;
1485 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1487 Status = NtDuplicateToken( ProcessToken,
1488 TOKEN_IMPERSONATE,
1489 &ObjectAttributes,
1490 ImpersonationLevel,
1491 TokenImpersonation,
1492 &ImpersonationToken );
1493 if (Status != STATUS_SUCCESS)
1495 NtClose( ProcessToken );
1496 return Status;
1499 Status = NtSetInformationThread( GetCurrentThread(),
1500 ThreadImpersonationToken,
1501 &ImpersonationToken,
1502 sizeof(ImpersonationToken) );
1504 NtClose( ImpersonationToken );
1505 NtClose( ProcessToken );
1507 return Status;
1510 /******************************************************************************
1511 * NtAccessCheck [NTDLL.@]
1512 * ZwAccessCheck [NTDLL.@]
1514 * Checks that a user represented by a token is allowed to access an object
1515 * represented by a security descriptor.
1517 * PARAMS
1518 * SecurityDescriptor [I] The security descriptor of the object to check.
1519 * ClientToken [I] Token of the user accessing the object.
1520 * DesiredAccess [I] The desired access to the object.
1521 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1522 * PrivilegeSet [I/O] Privileges used during the access check.
1523 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1524 * GrantedAccess [O] The actual access rights granted.
1525 * AccessStatus [O] The status of the access check.
1527 * RETURNS
1528 * NTSTATUS code.
1530 * NOTES
1531 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1532 * the maximum access rights allowed by the SD and returns them in
1533 * GrantedAccess.
1534 * The SecurityDescriptor must have a valid owner and groups present,
1535 * otherwise the function will fail.
1537 NTSTATUS WINAPI
1538 NtAccessCheck(
1539 PSECURITY_DESCRIPTOR SecurityDescriptor,
1540 HANDLE ClientToken,
1541 ACCESS_MASK DesiredAccess,
1542 PGENERIC_MAPPING GenericMapping,
1543 PPRIVILEGE_SET PrivilegeSet,
1544 PULONG ReturnLength,
1545 PULONG GrantedAccess,
1546 NTSTATUS *AccessStatus)
1548 NTSTATUS status;
1550 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1551 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1552 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1554 if (!PrivilegeSet || !ReturnLength)
1555 return STATUS_ACCESS_VIOLATION;
1557 SERVER_START_REQ( access_check )
1559 struct security_descriptor sd;
1560 PSID owner;
1561 PSID group;
1562 PACL sacl;
1563 PACL dacl;
1564 BOOLEAN defaulted, present;
1565 DWORD revision;
1566 SECURITY_DESCRIPTOR_CONTROL control;
1568 req->handle = wine_server_obj_handle( ClientToken );
1569 req->desired_access = DesiredAccess;
1570 req->mapping_read = GenericMapping->GenericRead;
1571 req->mapping_write = GenericMapping->GenericWrite;
1572 req->mapping_execute = GenericMapping->GenericExecute;
1573 req->mapping_all = GenericMapping->GenericAll;
1575 /* marshal security descriptor */
1576 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1577 sd.control = control & ~SE_SELF_RELATIVE;
1578 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1579 sd.owner_len = RtlLengthSid( owner );
1580 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1581 sd.group_len = RtlLengthSid( group );
1582 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1583 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1584 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1585 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1587 wine_server_add_data( req, &sd, sizeof(sd) );
1588 wine_server_add_data( req, owner, sd.owner_len );
1589 wine_server_add_data( req, group, sd.group_len );
1590 wine_server_add_data( req, sacl, sd.sacl_len );
1591 wine_server_add_data( req, dacl, sd.dacl_len );
1593 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1595 status = wine_server_call( req );
1597 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1598 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1600 if (status == STATUS_SUCCESS)
1602 *AccessStatus = reply->access_status;
1603 *GrantedAccess = reply->access_granted;
1606 SERVER_END_REQ;
1608 return status;
1611 /******************************************************************************
1612 * NtSetSecurityObject [NTDLL.@]
1613 * ZwSetSecurityObject [NTDLL.@]
1615 * Sets specified parts of the object's security descriptor.
1617 * PARAMS
1618 * Handle [I] Handle to the object to change security descriptor of.
1619 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1620 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1622 * RETURNS
1623 * NTSTATUS code.
1626 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1627 SECURITY_INFORMATION SecurityInformation,
1628 PSECURITY_DESCRIPTOR SecurityDescriptor)
1630 NTSTATUS status;
1631 struct security_descriptor sd;
1632 PACL dacl = NULL, sacl = NULL;
1633 PSID owner = NULL, group = NULL;
1634 BOOLEAN defaulted, present;
1635 DWORD revision;
1636 SECURITY_DESCRIPTOR_CONTROL control;
1638 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1640 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1642 memset( &sd, 0, sizeof(sd) );
1643 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1644 if (status != STATUS_SUCCESS) return status;
1645 sd.control = control & ~SE_SELF_RELATIVE;
1647 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1649 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1650 if (status != STATUS_SUCCESS) return status;
1651 if (!(sd.owner_len = RtlLengthSid( owner )))
1652 return STATUS_INVALID_SECURITY_DESCR;
1655 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1657 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1658 if (status != STATUS_SUCCESS) return status;
1659 if (!(sd.group_len = RtlLengthSid( group )))
1660 return STATUS_INVALID_SECURITY_DESCR;
1663 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1665 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1666 if (status != STATUS_SUCCESS) return status;
1667 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1668 sd.control |= SE_SACL_PRESENT;
1671 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1673 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1674 if (status != STATUS_SUCCESS) return status;
1675 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1676 sd.control |= SE_DACL_PRESENT;
1679 SERVER_START_REQ( set_security_object )
1681 req->handle = wine_server_obj_handle( Handle );
1682 req->security_info = SecurityInformation;
1684 wine_server_add_data( req, &sd, sizeof(sd) );
1685 wine_server_add_data( req, owner, sd.owner_len );
1686 wine_server_add_data( req, group, sd.group_len );
1687 wine_server_add_data( req, sacl, sd.sacl_len );
1688 wine_server_add_data( req, dacl, sd.dacl_len );
1689 status = wine_server_call( req );
1691 SERVER_END_REQ;
1693 return status;
1696 /******************************************************************************
1697 * RtlConvertSidToUnicodeString (NTDLL.@)
1699 * The returned SID is used to access the USER registry hive usually
1701 * the native function returns something like
1702 * "S-1-5-21-0000000000-000000000-0000000000-500";
1704 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1705 PUNICODE_STRING String,
1706 PSID pSid,
1707 BOOLEAN AllocateString)
1709 static const WCHAR formatW[] = {'-','%','u',0};
1710 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1711 WCHAR *p = buffer;
1712 const SID *sid = pSid;
1713 DWORD i, len;
1715 *p++ = 'S';
1716 p += sprintfW( p, formatW, sid->Revision );
1717 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1718 sid->IdentifierAuthority.Value[4] ),
1719 MAKEWORD( sid->IdentifierAuthority.Value[3],
1720 sid->IdentifierAuthority.Value[2] )));
1721 for (i = 0; i < sid->SubAuthorityCount; i++)
1722 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1724 len = (p + 1 - buffer) * sizeof(WCHAR);
1726 String->Length = len - sizeof(WCHAR);
1727 if (AllocateString)
1729 String->MaximumLength = len;
1730 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1731 return STATUS_NO_MEMORY;
1733 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1735 memcpy( String->Buffer, buffer, len );
1736 return STATUS_SUCCESS;
1739 /******************************************************************************
1740 * RtlQueryInformationAcl (NTDLL.@)
1742 NTSTATUS WINAPI RtlQueryInformationAcl(
1743 PACL pAcl,
1744 LPVOID pAclInformation,
1745 DWORD nAclInformationLength,
1746 ACL_INFORMATION_CLASS dwAclInformationClass)
1748 NTSTATUS status = STATUS_SUCCESS;
1750 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1751 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1753 switch (dwAclInformationClass)
1755 case AclRevisionInformation:
1757 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1759 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1760 status = STATUS_INVALID_PARAMETER;
1761 else
1762 paclrev->AclRevision = pAcl->AclRevision;
1764 break;
1767 case AclSizeInformation:
1769 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1771 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1772 status = STATUS_INVALID_PARAMETER;
1773 else
1775 paclsize->AceCount = pAcl->AceCount;
1776 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1777 if (pAcl->AclSize < paclsize->AclBytesInUse)
1779 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1780 paclsize->AclBytesFree = 0;
1781 paclsize->AclBytesInUse = pAcl->AclSize;
1783 else
1784 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1787 break;
1790 default:
1791 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1792 status = STATUS_INVALID_PARAMETER;
1795 return status;