1 /*
2 * Security functions
3 *
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "config.h"
23 #include "wine/port.h"
24
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
34
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
45
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
47
48 /* helper function to retrieve active length of an ACL */
49 static size_t acl_bytesInUse(PACL pAcl)
50 {
51 int i;
52 size_t bytesInUse = sizeof(ACL);
53 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
54 for (i = 0; i < pAcl->AceCount; i++)
55 {
56 bytesInUse += ace->AceSize;
57 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
58 }
59 return bytesInUse;
60 }
61
62 /* helper function to copy an ACL */
63 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
64 {
65 DWORD size;
66
67 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
68 return FALSE;
69
70 size = pSourceAcl->AclSize;
71 if (nDestinationAclLength < size)
72 return FALSE;
73
74 memmove(pDestinationAcl, pSourceAcl, size);
75 return TRUE;
76 }
77
78 /* generically adds an ACE to an ACL */
79 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
80 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
81 {
82 ACE_HEADER *pAceHeader;
83 DWORD dwLengthSid;
84 DWORD dwAceSize;
85 DWORD *pAccessMask;
86 DWORD *pSidStart;
87
88 if (!RtlValidSid(pSid))
89 return STATUS_INVALID_SID;
90
91 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
92 return STATUS_REVISION_MISMATCH;
93
94 if (!RtlValidAcl(pAcl))
95 return STATUS_INVALID_ACL;
96
97 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
98 return STATUS_INVALID_ACL;
99
100 if (!pAceHeader)
101 return STATUS_ALLOTTED_SPACE_EXCEEDED;
102
103 /* calculate generic size of the ACE */
104 dwLengthSid = RtlLengthSid(pSid);
105 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
106 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
107 return STATUS_ALLOTTED_SPACE_EXCEEDED;
108
109 /* fill the new ACE */
110 pAceHeader->AceType = dwAceType;
111 pAceHeader->AceFlags = dwAceFlags;
112 pAceHeader->AceSize = dwAceSize;
113
114 /* skip past the ACE_HEADER of the ACE */
115 pAccessMask = (DWORD *)(pAceHeader + 1);
116 *pAccessMask = dwAccessMask;
117
118 /* skip past ACE->Mask */
119 pSidStart = pAccessMask + 1;
120 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
121
122 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
123 pAcl->AceCount++;
124
125 return STATUS_SUCCESS;
126 }
127
128 /*
129 * SID FUNCTIONS
130 */
131
132 /******************************************************************************
133 * RtlAllocateAndInitializeSid [NTDLL.@]
134 *
135 */
136 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
137 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
138 BYTE nSubAuthorityCount,
139 DWORD nSubAuthority0, DWORD nSubAuthority1,
140 DWORD nSubAuthority2, DWORD nSubAuthority3,
141 DWORD nSubAuthority4, DWORD nSubAuthority5,
142 DWORD nSubAuthority6, DWORD nSubAuthority7,
143 PSID *pSid )
144 {
145 SID *tmp_sid;
146
147 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
148 pIdentifierAuthority,nSubAuthorityCount,
149 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
150 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
151
152 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
153
154 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
155 RtlLengthRequiredSid(nSubAuthorityCount))))
156 return STATUS_NO_MEMORY;
157
158 tmp_sid->Revision = SID_REVISION;
159
160 if (pIdentifierAuthority)
161 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
162 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
163
164 switch( nSubAuthorityCount )
165 {
166 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
167 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
168 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
169 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
170 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
171 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
172 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
173 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
174 break;
175 }
176 *pSid = tmp_sid;
177 return STATUS_SUCCESS;
178 }
179
180 /******************************************************************************
181 * RtlEqualSid [NTDLL.@]
182 *
183 * Determine if two SIDs are equal.
184 *
185 * PARAMS
186 * pSid1 [I] Source SID
187 * pSid2 [I] SID to compare with
188 *
189 * RETURNS
190 * TRUE, if pSid1 is equal to pSid2,
191 * FALSE otherwise.
192 */
193 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
194 {
195 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
196 return FALSE;
197
198 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
199 return FALSE;
200
201 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
202 return FALSE;
203
204 return TRUE;
205 }
206
207 /******************************************************************************
208 * RtlEqualPrefixSid [NTDLL.@]
209 */
210 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
211 {
212 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
213 return FALSE;
214
215 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
216 return FALSE;
217
218 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
219 return FALSE;
220
221 return TRUE;
222 }
223
224
225 /******************************************************************************
226 * RtlFreeSid [NTDLL.@]
227 *
228 * Free the resources used by a SID.
229 *
230 * PARAMS
231 * pSid [I] SID to Free.
232 *
233 * RETURNS
234 * STATUS_SUCCESS.
235 */
236 DWORD WINAPI RtlFreeSid(PSID pSid)
237 {
238 TRACE("(%p)\n", pSid);
239 RtlFreeHeap( GetProcessHeap(), 0, pSid );
240 return STATUS_SUCCESS;
241 }
242
243 /**************************************************************************
244 * RtlLengthRequiredSid [NTDLL.@]
245 *
246 * Determine the amount of memory a SID will use
247 *
248 * PARAMS
249 * nrofsubauths [I] Number of Sub Authorities in the SID.
250 *
251 * RETURNS
252 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
253 */
254 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
255 {
256 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
257 }
258
259 /**************************************************************************
260 * RtlLengthSid [NTDLL.@]
261 *
262 * Determine the amount of memory a SID is using
263 *
264 * PARAMS
265 * pSid [I] SID to get the size of.
266 *
267 * RETURNS
268 * The size, in bytes, of pSid.
269 */
270 DWORD WINAPI RtlLengthSid(PSID pSid)
271 {
272 TRACE("sid=%p\n",pSid);
273 if (!pSid) return 0;
274 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
275 }
276
277 /**************************************************************************
278 * RtlInitializeSid [NTDLL.@]
279 *
280 * Initialise a SID.
281 *
282 * PARAMS
283 * pSid [I] SID to initialise
284 * pIdentifierAuthority [I] Identifier Authority
285 * nSubAuthorityCount [I] Number of Sub Authorities
286 *
287 * RETURNS
288 * Success: TRUE. pSid is initialised with the details given.
289 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
290 */
291 BOOL WINAPI RtlInitializeSid(
292 PSID pSid,
293 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
294 BYTE nSubAuthorityCount)
295 {
296 int i;
297 SID* pisid=pSid;
298
299 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
300 return FALSE;
301
302 pisid->Revision = SID_REVISION;
303 pisid->SubAuthorityCount = nSubAuthorityCount;
304 if (pIdentifierAuthority)
305 pisid->IdentifierAuthority = *pIdentifierAuthority;
306
307 for (i = 0; i < nSubAuthorityCount; i++)
308 *RtlSubAuthoritySid(pSid, i) = 0;
309
310 return TRUE;
311 }
312
313 /**************************************************************************
314 * RtlSubAuthoritySid [NTDLL.@]
315 *
316 * Return the Sub Authority of a SID
317 *
318 * PARAMS
319 * pSid [I] SID to get the Sub Authority from.
320 * nSubAuthority [I] Sub Authority number.
321 *
322 * RETURNS
323 * A pointer to The Sub Authority value of pSid.
324 */
325 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
326 {
327 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
328 }
329
330 /**************************************************************************
331 * RtlIdentifierAuthoritySid [NTDLL.@]
332 *
333 * Return the Identifier Authority of a SID.
334 *
335 * PARAMS
336 * pSid [I] SID to get the Identifier Authority from.
337 *
338 * RETURNS
339 * A pointer to the Identifier Authority value of pSid.
340 */
341 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
342 {
343 return &(((SID*)pSid)->IdentifierAuthority);
344 }
345
346 /**************************************************************************
347 * RtlSubAuthorityCountSid [NTDLL.@]
348 *
349 * Get the number of Sub Authorities in a SID.
350 *
351 * PARAMS
352 * pSid [I] SID to get the count from.
353 *
354 * RETURNS
355 * A pointer to the Sub Authority count of pSid.
356 */
357 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
358 {
359 return &(((SID*)pSid)->SubAuthorityCount);
360 }
361
362 /**************************************************************************
363 * RtlCopySid [NTDLL.@]
364 */
365 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
366 {
367 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
368 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
369 return FALSE;
370
371 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
372 return FALSE;
373
374 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
375 return TRUE;
376 }
377 /******************************************************************************
378 * RtlValidSid [NTDLL.@]
379 *
380 * Determine if a SID is valid.
381 *
382 * PARAMS
383 * pSid [I] SID to check
384 *
385 * RETURNS
386 * TRUE if pSid is valid,
387 * FALSE otherwise.
388 */
389 BOOLEAN WINAPI RtlValidSid( PSID pSid )
390 {
391 BOOL ret;
392 __TRY
393 {
394 ret = TRUE;
395 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
396 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
397 {
398 ret = FALSE;
399 }
400 }
401 __EXCEPT_PAGE_FAULT
402 {
403 WARN("(%p): invalid pointer!\n", pSid);
404 return FALSE;
405 }
406 __ENDTRY
407 return ret;
408 }
409
410
411 /*
412 * security descriptor functions
413 */
414
415 /**************************************************************************
416 * RtlCreateSecurityDescriptor [NTDLL.@]
417 *
418 * Initialise a SECURITY_DESCRIPTOR.
419 *
420 * PARAMS
421 * lpsd [O] Descriptor to initialise.
422 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
423 *
424 * RETURNS
425 * Success: STATUS_SUCCESS.
426 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
427 */
428 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
429 PSECURITY_DESCRIPTOR lpsd,
430 DWORD rev)
431 {
432 if (rev!=SECURITY_DESCRIPTOR_REVISION)
433 return STATUS_UNKNOWN_REVISION;
434 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
435 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
436 return STATUS_SUCCESS;
437 }
438
439 /**************************************************************************
440 * RtlCopySecurityDescriptor [NTDLL.@]
441 *
442 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
443 *
444 * PARAMS
445 * pSourceSD [O] SD to copy from.
446 * pDestinationSD [I] Destination SD.
447 *
448 * RETURNS
449 * Success: STATUS_SUCCESS.
450 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
451 */
452 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
453 {
454 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
455 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
456 PSID Owner, Group;
457 PACL Dacl, Sacl;
458 BOOLEAN defaulted, present;
459 DWORD length;
460 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
461
462 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
464
465 /* copy initial data */
466 destSD->Revision = srcSD->Revision;
467 destSD->Sbz1 = srcSD->Sbz1;
468 destSD->Control = srcSD->Control;
469
470 /* copy Owner */
471 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
472 length = RtlLengthSid(Owner);
473
474 if (isSelfRelative)
475 {
476 destSD->Owner = srcSD->Owner;
477 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
478 }
479 else
480 {
481 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
482 RtlCopySid(length, destSD->Owner, Owner);
483 }
484
485 /* copy Group */
486 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
487 length = RtlLengthSid(Group);
488
489 if (isSelfRelative)
490 {
491 destSD->Group = srcSD->Group;
492 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
493 }
494 else
495 {
496 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
497 RtlCopySid(length, destSD->Group, Group);
498 }
499
500 /* copy Dacl */
501 if (srcSD->Control & SE_DACL_PRESENT)
502 {
503 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
504 length = Dacl->AclSize;
505
506 if (isSelfRelative)
507 {
508 destSD->Dacl = srcSD->Dacl;
509 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
510 }
511 else
512 {
513 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, destSD->Dacl, Dacl);
515 }
516 }
517
518 /* copy Sacl */
519 if (srcSD->Control & SE_SACL_PRESENT)
520 {
521 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
522 length = Sacl->AclSize;
523
524 if (isSelfRelative)
525 {
526 destSD->Sacl = srcSD->Sacl;
527 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
528 }
529 else
530 {
531 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
532 copy_acl(length, destSD->Sacl, Sacl);
533 }
534 }
535
536 return STATUS_SUCCESS;
537 }
538
539 /**************************************************************************
540 * RtlValidSecurityDescriptor [NTDLL.@]
541 *
542 * Determine if a SECURITY_DESCRIPTOR is valid.
543 *
544 * PARAMS
545 * SecurityDescriptor [I] Descriptor to check.
546 *
547 * RETURNS
548 * Success: STATUS_SUCCESS.
549 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
550 */
551 NTSTATUS WINAPI RtlValidSecurityDescriptor(
552 PSECURITY_DESCRIPTOR SecurityDescriptor)
553 {
554 if ( ! SecurityDescriptor )
555 return STATUS_INVALID_SECURITY_DESCR;
556 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
557 return STATUS_UNKNOWN_REVISION;
558
559 return STATUS_SUCCESS;
560 }
561
562 /**************************************************************************
563 * RtlLengthSecurityDescriptor [NTDLL.@]
564 */
565 ULONG WINAPI RtlLengthSecurityDescriptor(
566 PSECURITY_DESCRIPTOR pSecurityDescriptor)
567 {
568 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
569 ULONG_PTR offset = 0;
570 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
571
572 if ( lpsd == NULL )
573 return 0;
574
575 if ( lpsd->Control & SE_SELF_RELATIVE)
576 offset = (ULONG_PTR) lpsd;
577
578 if ( lpsd->Owner != NULL )
579 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
580
581 if ( lpsd->Group != NULL )
582 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
583
584 if ( (lpsd->Control & SE_SACL_PRESENT) &&
585 lpsd->Sacl != NULL )
586 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
587
588 if ( (lpsd->Control & SE_DACL_PRESENT) &&
589 lpsd->Dacl != NULL )
590 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
591
592 return Size;
593 }
594
595 /******************************************************************************
596 * RtlGetDaclSecurityDescriptor [NTDLL.@]
597 *
598 */
599 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
600 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
601 OUT PBOOLEAN lpbDaclPresent,
602 OUT PACL *pDacl,
603 OUT PBOOLEAN lpbDaclDefaulted)
604 {
605 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606
607 TRACE("(%p,%p,%p,%p)\n",
608 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609
610 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
611 return STATUS_UNKNOWN_REVISION ;
612
613 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614 {
615 if ( SE_SELF_RELATIVE & lpsd->Control)
616 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
617 else
618 *pDacl = lpsd->Dacl;
619
620 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
621 }
622
623 return STATUS_SUCCESS;
624 }
625
626 /**************************************************************************
627 * RtlSetDaclSecurityDescriptor [NTDLL.@]
628 */
629 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
630 PSECURITY_DESCRIPTOR pSecurityDescriptor,
631 BOOLEAN daclpresent,
632 PACL dacl,
633 BOOLEAN dacldefaulted )
634 {
635 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
636
637 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
638 return STATUS_UNKNOWN_REVISION;
639 if (lpsd->Control & SE_SELF_RELATIVE)
640 return STATUS_INVALID_SECURITY_DESCR;
641
642 if (!daclpresent)
643 {
644 lpsd->Control &= ~SE_DACL_PRESENT;
645 return STATUS_SUCCESS;
646 }
647
648 lpsd->Control |= SE_DACL_PRESENT;
649 lpsd->Dacl = dacl;
650
651 if (dacldefaulted)
652 lpsd->Control |= SE_DACL_DEFAULTED;
653 else
654 lpsd->Control &= ~SE_DACL_DEFAULTED;
655
656 return STATUS_SUCCESS;
657 }
658
659 /******************************************************************************
660 * RtlGetSaclSecurityDescriptor [NTDLL.@]
661 *
662 */
663 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
664 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
665 OUT PBOOLEAN lpbSaclPresent,
666 OUT PACL *pSacl,
667 OUT PBOOLEAN lpbSaclDefaulted)
668 {
669 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
670
671 TRACE("(%p,%p,%p,%p)\n",
672 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
673
674 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
675 return STATUS_UNKNOWN_REVISION;
676
677 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
678 {
679 if (SE_SELF_RELATIVE & lpsd->Control)
680 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
681 else
682 *pSacl = lpsd->Sacl;
683
684 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
685 }
686
687 return STATUS_SUCCESS;
688 }
689
690 /**************************************************************************
691 * RtlSetSaclSecurityDescriptor [NTDLL.@]
692 */
693 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
694 PSECURITY_DESCRIPTOR pSecurityDescriptor,
695 BOOLEAN saclpresent,
696 PACL sacl,
697 BOOLEAN sacldefaulted)
698 {
699 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
700
701 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
702 return STATUS_UNKNOWN_REVISION;
703 if (lpsd->Control & SE_SELF_RELATIVE)
704 return STATUS_INVALID_SECURITY_DESCR;
705 if (!saclpresent) {
706 lpsd->Control &= ~SE_SACL_PRESENT;
707 return 0;
708 }
709 lpsd->Control |= SE_SACL_PRESENT;
710 lpsd->Sacl = sacl;
711 if (sacldefaulted)
712 lpsd->Control |= SE_SACL_DEFAULTED;
713 else
714 lpsd->Control &= ~SE_SACL_DEFAULTED;
715 return STATUS_SUCCESS;
716 }
717
718 /**************************************************************************
719 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
720 */
721 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
722 PSECURITY_DESCRIPTOR pSecurityDescriptor,
723 PSID *Owner,
724 PBOOLEAN OwnerDefaulted)
725 {
726 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
727
728 if ( !lpsd || !Owner || !OwnerDefaulted )
729 return STATUS_INVALID_PARAMETER;
730
731 if ( lpsd->Control & SE_OWNER_DEFAULTED )
732 *OwnerDefaulted = TRUE;
733 else
734 *OwnerDefaulted = FALSE;
735
736 if (lpsd->Owner != NULL)
737 {
738 if (lpsd->Control & SE_SELF_RELATIVE)
739 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
740 else
741 *Owner = lpsd->Owner;
742
743 }
744 else
745 *Owner = NULL;
746
747 return STATUS_SUCCESS;
748 }
749
750 /**************************************************************************
751 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
752 */
753 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
754 PSECURITY_DESCRIPTOR pSecurityDescriptor,
755 PSID owner,
756 BOOLEAN ownerdefaulted)
757 {
758 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
759
760 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
761 return STATUS_UNKNOWN_REVISION;
762 if (lpsd->Control & SE_SELF_RELATIVE)
763 return STATUS_INVALID_SECURITY_DESCR;
764
765 lpsd->Owner = owner;
766 if (ownerdefaulted)
767 lpsd->Control |= SE_OWNER_DEFAULTED;
768 else
769 lpsd->Control &= ~SE_OWNER_DEFAULTED;
770 return STATUS_SUCCESS;
771 }
772
773 /**************************************************************************
774 * RtlSetGroupSecurityDescriptor [NTDLL.@]
775 */
776 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
777 PSECURITY_DESCRIPTOR pSecurityDescriptor,
778 PSID group,
779 BOOLEAN groupdefaulted)
780 {
781 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
782
783 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
784 return STATUS_UNKNOWN_REVISION;
785 if (lpsd->Control & SE_SELF_RELATIVE)
786 return STATUS_INVALID_SECURITY_DESCR;
787
788 lpsd->Group = group;
789 if (groupdefaulted)
790 lpsd->Control |= SE_GROUP_DEFAULTED;
791 else
792 lpsd->Control &= ~SE_GROUP_DEFAULTED;
793 return STATUS_SUCCESS;
794 }
795
796 /**************************************************************************
797 * RtlGetGroupSecurityDescriptor [NTDLL.@]
798 */
799 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
800 PSECURITY_DESCRIPTOR pSecurityDescriptor,
801 PSID *Group,
802 PBOOLEAN GroupDefaulted)
803 {
804 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
805
806 if ( !lpsd || !Group || !GroupDefaulted )
807 return STATUS_INVALID_PARAMETER;
808
809 if ( lpsd->Control & SE_GROUP_DEFAULTED )
810 *GroupDefaulted = TRUE;
811 else
812 *GroupDefaulted = FALSE;
813
814 if (lpsd->Group != NULL)
815 {
816 if (lpsd->Control & SE_SELF_RELATIVE)
817 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
818 else
819 *Group = lpsd->Group;
820 }
821 else
822 *Group = NULL;
823
824 return STATUS_SUCCESS;
825 }
826
827 /**************************************************************************
828 * RtlMakeSelfRelativeSD [NTDLL.@]
829 */
830 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
831 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
832 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
833 IN OUT LPDWORD lpdwBufferLength)
834 {
835 ULONG_PTR offsetRel;
836 ULONG length;
837 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
838 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
839
840 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
841 lpdwBufferLength ? *lpdwBufferLength: -1);
842
843 if (!lpdwBufferLength || !pAbs)
844 return STATUS_INVALID_PARAMETER;
845
846 length = RtlLengthSecurityDescriptor(pAbs);
847 if (*lpdwBufferLength < length)
848 {
849 *lpdwBufferLength = length;
850 return STATUS_BUFFER_TOO_SMALL;
851 }
852
853 if (!pRel)
854 return STATUS_INVALID_PARAMETER;
855
856 if (pAbs->Control & SE_SELF_RELATIVE)
857 {
858 memcpy(pRel, pAbs, length);
859 return STATUS_SUCCESS;
860 }
861
862 pRel->Revision = pAbs->Revision;
863 pRel->Sbz1 = pAbs->Sbz1;
864 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
865
866 offsetRel = sizeof(SECURITY_DESCRIPTOR);
867 if (pAbs->Owner)
868 {
869 pRel->Owner = (PSID) offsetRel;
870 length = RtlLengthSid(pAbs->Owner);
871 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
872 offsetRel += length;
873 }
874 else
875 {
876 pRel->Owner = NULL;
877 }
878
879 if (pAbs->Group)
880 {
881 pRel->Group = (PSID) offsetRel;
882 length = RtlLengthSid(pAbs->Group);
883 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
884 offsetRel += length;
885 }
886 else
887 {
888 pRel->Group = NULL;
889 }
890
891 if (pAbs->Sacl)
892 {
893 pRel->Sacl = (PACL) offsetRel;
894 length = pAbs->Sacl->AclSize;
895 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
896 offsetRel += length;
897 }
898 else
899 {
900 pRel->Sacl = NULL;
901 }
902
903 if (pAbs->Dacl)
904 {
905 pRel->Dacl = (PACL) offsetRel;
906 length = pAbs->Dacl->AclSize;
907 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
908 }
909 else
910 {
911 pRel->Dacl = NULL;
912 }
913
914 return STATUS_SUCCESS;
915 }
916
917
918 /**************************************************************************
919 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
920 */
921 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
922 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
923 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
924 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
925 OUT PACL pDacl,
926 OUT LPDWORD lpdwDaclSize,
927 OUT PACL pSacl,
928 OUT LPDWORD lpdwSaclSize,
929 OUT PSID pOwner,
930 OUT LPDWORD lpdwOwnerSize,
931 OUT PSID pPrimaryGroup,
932 OUT LPDWORD lpdwPrimaryGroupSize)
933 {
934 NTSTATUS status = STATUS_SUCCESS;
935 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
936 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
937
938 if (!pRel ||
939 !lpdwAbsoluteSecurityDescriptorSize ||
940 !lpdwDaclSize ||
941 !lpdwSaclSize ||
942 !lpdwOwnerSize ||
943 !lpdwPrimaryGroupSize ||
944 ~pRel->Control & SE_SELF_RELATIVE)
945 return STATUS_INVALID_PARAMETER;
946
947 /* Confirm buffers are sufficiently large */
948 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
949 {
950 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
951 status = STATUS_BUFFER_TOO_SMALL;
952 }
953
954 if (pRel->Control & SE_DACL_PRESENT &&
955 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
956 {
957 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
959 }
960
961 if (pRel->Control & SE_SACL_PRESENT &&
962 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
963 {
964 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
965 status = STATUS_BUFFER_TOO_SMALL;
966 }
967
968 if (pRel->Owner &&
969 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
970 {
971 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
972 status = STATUS_BUFFER_TOO_SMALL;
973 }
974
975 if (pRel->Group &&
976 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
977 {
978 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
979 status = STATUS_BUFFER_TOO_SMALL;
980 }
981
982 if (status != STATUS_SUCCESS)
983 return status;
984
985 /* Copy structures, and clear the ones we don't set */
986 pAbs->Revision = pRel->Revision;
987 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
988 pAbs->Sacl = NULL;
989 pAbs->Dacl = NULL;
990 pAbs->Owner = NULL;
991 pAbs->Group = NULL;
992
993 if (pRel->Control & SE_SACL_PRESENT)
994 {
995 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
996
997 memcpy(pSacl, pAcl, pAcl->AclSize);
998 pAbs->Sacl = pSacl;
999 }
1000
1001 if (pRel->Control & SE_DACL_PRESENT)
1002 {
1003 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1004 memcpy(pDacl, pAcl, pAcl->AclSize);
1005 pAbs->Dacl = pDacl;
1006 }
1007
1008 if (pRel->Owner)
1009 {
1010 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1011 memcpy(pOwner, psid, RtlLengthSid(psid));
1012 pAbs->Owner = pOwner;
1013 }
1014
1015 if (pRel->Group)
1016 {
1017 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1018 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1019 pAbs->Group = pPrimaryGroup;
1020 }
1021
1022 return status;
1023 }
1024
1025 /******************************************************************************
1026 * RtlGetControlSecurityDescriptor (NTDLL.@)
1027 */
1028 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1029 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1030 PSECURITY_DESCRIPTOR_CONTROL pControl,
1031 LPDWORD lpdwRevision)
1032 {
1033 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1034
1035 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1036
1037 *lpdwRevision = lpsd->Revision;
1038
1039 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1040 return STATUS_UNKNOWN_REVISION;
1041
1042 *pControl = lpsd->Control;
1043
1044 return STATUS_SUCCESS;
1045 }
1046
1047 /******************************************************************************
1048 * RtlSetControlSecurityDescriptor (NTDLL.@)
1049 */
1050 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1051 PSECURITY_DESCRIPTOR SecurityDescriptor,
1052 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1053 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1054 {
1055 FIXME("(%p 0x%08x 0x%08x): stub\n", SecurityDescriptor, ControlBitsOfInterest,
1056 ControlBitsToSet);
1057 return STATUS_SUCCESS;
1058 }
1059
1060
1061 /**************************************************************************
1062 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1063 */
1064 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1065 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1066 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1067 PULONG BufferLength)
1068 {
1069 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1070
1071 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1072 SelfRelativeSecurityDescriptor, BufferLength);
1073
1074 if (abs->Control & SE_SELF_RELATIVE)
1075 return STATUS_BAD_DESCRIPTOR_FORMAT;
1076
1077 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1078 SelfRelativeSecurityDescriptor, BufferLength);
1079 }
1080
1081
1082 /*
1083 * access control list's
1084 */
1085
1086 /**************************************************************************
1087 * RtlCreateAcl [NTDLL.@]
1088 *
1089 * NOTES
1090 * This should return NTSTATUS
1091 */
1092 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1093 {
1094 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1095
1096 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1097 return STATUS_INVALID_PARAMETER;
1098 if (size<sizeof(ACL))
1099 return STATUS_BUFFER_TOO_SMALL;
1100 if (size>0xFFFF)
1101 return STATUS_INVALID_PARAMETER;
1102
1103 memset(acl,'\0',sizeof(ACL));
1104 acl->AclRevision = rev;
1105 acl->AclSize = size;
1106 acl->AceCount = 0;
1107 return STATUS_SUCCESS;
1108 }
1109
1110 /**************************************************************************
1111 * RtlFirstFreeAce [NTDLL.@]
1112 * looks for the AceCount+1 ACE, and if it is still within the alloced
1113 * ACL, return a pointer to it
1114 */
1115 BOOLEAN WINAPI RtlFirstFreeAce(
1116 PACL acl,
1117 PACE_HEADER *x)
1118 {
1119 PACE_HEADER ace;
1120 int i;
1121
1122 *x = 0;
1123 ace = (PACE_HEADER)(acl+1);
1124 for (i=0;i<acl->AceCount;i++) {
1125 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1126 return 0;
1127 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1128 }
1129 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1130 return 0;
1131 *x = ace;
1132 return 1;
1133 }
1134
1135 /**************************************************************************
1136 * RtlAddAce [NTDLL.@]
1137 */
1138 NTSTATUS WINAPI RtlAddAce(
1139 PACL acl,
1140 DWORD rev,
1141 DWORD xnrofaces,
1142 PACE_HEADER acestart,
1143 DWORD acelen)
1144 {
1145 PACE_HEADER ace,targetace;
1146 int nrofaces;
1147
1148 if (acl->AclRevision != ACL_REVISION)
1149 return STATUS_INVALID_PARAMETER;
1150 if (!RtlFirstFreeAce(acl,&targetace))
1151 return STATUS_INVALID_PARAMETER;
1152 nrofaces=0;ace=acestart;
1153 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1154 nrofaces++;
1155 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1156 }
1157 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1158 return STATUS_INVALID_PARAMETER;
1159 memcpy((LPBYTE)targetace,acestart,acelen);
1160 acl->AceCount+=nrofaces;
1161 return STATUS_SUCCESS;
1162 }
1163
1164 /**************************************************************************
1165 * RtlDeleteAce [NTDLL.@]
1166 */
1167 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1168 {
1169 NTSTATUS status;
1170 PACE_HEADER pAce;
1171
1172 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1173
1174 if (STATUS_SUCCESS == status)
1175 {
1176 PACE_HEADER pcAce;
1177 DWORD len = 0;
1178
1179 /* skip over the ACE we are deleting */
1180 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1181 dwAceIndex++;
1182
1183 /* calculate the length of the rest */
1184 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1185 {
1186 len += pcAce->AceSize;
1187 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1188 }
1189
1190 /* slide them all backwards */
1191 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1192 pAcl->AceCount--;
1193 }
1194
1195 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1196
1197 return status;
1198 }
1199
1200 /******************************************************************************
1201 * RtlAddAccessAllowedAce [NTDLL.@]
1202 */
1203 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1204 IN OUT PACL pAcl,
1205 IN DWORD dwAceRevision,
1206 IN DWORD AccessMask,
1207 IN PSID pSid)
1208 {
1209 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1210 }
1211
1212 /******************************************************************************
1213 * RtlAddAccessAllowedAceEx [NTDLL.@]
1214 */
1215 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1216 IN OUT PACL pAcl,
1217 IN DWORD dwAceRevision,
1218 IN DWORD AceFlags,
1219 IN DWORD AccessMask,
1220 IN PSID pSid)
1221 {
1222 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1223
1224 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1225 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1226 }
1227
1228 /******************************************************************************
1229 * RtlAddAccessDeniedAce [NTDLL.@]
1230 */
1231 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1232 IN OUT PACL pAcl,
1233 IN DWORD dwAceRevision,
1234 IN DWORD AccessMask,
1235 IN PSID pSid)
1236 {
1237 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1238 }
1239
1240 /******************************************************************************
1241 * RtlAddAccessDeniedAceEx [NTDLL.@]
1242 */
1243 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1244 IN OUT PACL pAcl,
1245 IN DWORD dwAceRevision,
1246 IN DWORD AceFlags,
1247 IN DWORD AccessMask,
1248 IN PSID pSid)
1249 {
1250 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1251
1252 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1253 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1254 }
1255
1256 /**************************************************************************
1257 * RtlAddAuditAccessAce [NTDLL.@]
1258 */
1259 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1260 IN OUT PACL pAcl,
1261 IN DWORD dwAceRevision,
1262 IN DWORD dwAceFlags,
1263 IN DWORD dwAccessMask,
1264 IN PSID pSid,
1265 IN BOOL bAuditSuccess,
1266 IN BOOL bAuditFailure)
1267 {
1268 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1269 pSid,bAuditSuccess,bAuditFailure);
1270
1271 if (bAuditSuccess)
1272 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1273
1274 if (bAuditFailure)
1275 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1276
1277 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1278 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1279 }
1280
1281 /**************************************************************************
1282 * RtlAddAuditAccessAce [NTDLL.@]
1283 */
1284 NTSTATUS WINAPI RtlAddAuditAccessAce(
1285 IN OUT PACL pAcl,
1286 IN DWORD dwAceRevision,
1287 IN DWORD dwAccessMask,
1288 IN PSID pSid,
1289 IN BOOL bAuditSuccess,
1290 IN BOOL bAuditFailure)
1291 {
1292 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1293 }
1294
1295 /******************************************************************************
1296 * RtlValidAcl [NTDLL.@]
1297 */
1298 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1299 {
1300 BOOLEAN ret;
1301 TRACE("(%p)\n", pAcl);
1302
1303 __TRY
1304 {
1305 PACE_HEADER ace;
1306 int i;
1307
1308 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1309 pAcl->AclRevision > MAX_ACL_REVISION)
1310 ret = FALSE;
1311 else
1312 {
1313 ace = (PACE_HEADER)(pAcl+1);
1314 ret = TRUE;
1315 for (i=0;i<=pAcl->AceCount;i++)
1316 {
1317 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1318 {
1319 ret = FALSE;
1320 break;
1321 }
1322 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1323 }
1324 }
1325 }
1326 __EXCEPT_PAGE_FAULT
1327 {
1328 WARN("(%p): invalid pointer!\n", pAcl);
1329 return 0;
1330 }
1331 __ENDTRY
1332 return ret;
1333 }
1334
1335 /******************************************************************************
1336 * RtlGetAce [NTDLL.@]
1337 */
1338 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1339 {
1340 PACE_HEADER ace;
1341
1342 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1343
1344 if (dwAceIndex >= pAcl->AceCount)
1345 return STATUS_INVALID_PARAMETER;
1346
1347 ace = (PACE_HEADER)(pAcl + 1);
1348 for (;dwAceIndex;dwAceIndex--)
1349 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1350
1351 *pAce = (LPVOID) ace;
1352
1353 return STATUS_SUCCESS;
1354 }
1355
1356 /*
1357 * misc
1358 */
1359
1360 /******************************************************************************
1361 * RtlAdjustPrivilege [NTDLL.@]
1362 *
1363 * Enables or disables a privilege from the calling thread or process.
1364 *
1365 * PARAMS
1366 * Privilege [I] Privilege index to change.
1367 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1368 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1369 * Enabled [O] Whether privilege was previously enabled or disabled.
1370 *
1371 * RETURNS
1372 * Success: STATUS_SUCCESS.
1373 * Failure: NTSTATUS code.
1374 *
1375 * SEE ALSO
1376 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1377 *
1378 */
1379 NTSTATUS WINAPI
1380 RtlAdjustPrivilege(ULONG Privilege,
1381 BOOLEAN Enable,
1382 BOOLEAN CurrentThread,
1383 PBOOLEAN Enabled)
1384 {
1385 TOKEN_PRIVILEGES NewState;
1386 TOKEN_PRIVILEGES OldState;
1387 ULONG ReturnLength;
1388 HANDLE TokenHandle;
1389 NTSTATUS Status;
1390
1391 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1392 CurrentThread ? "TRUE" : "FALSE", Enabled);
1393
1394 if (CurrentThread)
1395 {
1396 Status = NtOpenThreadToken(GetCurrentThread(),
1397 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1398 FALSE,
1399 &TokenHandle);
1400 }
1401 else
1402 {
1403 Status = NtOpenProcessToken(GetCurrentProcess(),
1404 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1405 &TokenHandle);
1406 }
1407
1408 if (!NT_SUCCESS(Status))
1409 {
1410 WARN("Retrieving token handle failed (Status %x)\n", Status);
1411 return Status;
1412 }
1413
1414 OldState.PrivilegeCount = 1;
1415
1416 NewState.PrivilegeCount = 1;
1417 NewState.Privileges[0].Luid.LowPart = Privilege;
1418 NewState.Privileges[0].Luid.HighPart = 0;
1419 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1420
1421 Status = NtAdjustPrivilegesToken(TokenHandle,
1422 FALSE,
1423 &NewState,
1424 sizeof(TOKEN_PRIVILEGES),
1425 &OldState,
1426 &ReturnLength);
1427 NtClose (TokenHandle);
1428 if (Status == STATUS_NOT_ALL_ASSIGNED)
1429 {
1430 TRACE("Failed to assign all privileges\n");
1431 return STATUS_PRIVILEGE_NOT_HELD;
1432 }
1433 if (!NT_SUCCESS(Status))
1434 {
1435 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1436 return Status;
1437 }
1438
1439 if (OldState.PrivilegeCount == 0)
1440 *Enabled = Enable;
1441 else
1442 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1443
1444 return STATUS_SUCCESS;
1445 }
1446
1447 /******************************************************************************
1448 * RtlImpersonateSelf [NTDLL.@]
1449 *
1450 * Makes an impersonation token that represents the process user and assigns
1451 * to the current thread.
1452 *
1453 * PARAMS
1454 * ImpersonationLevel [I] Level at which to impersonate.
1455 *
1456 * RETURNS
1457 * Success: STATUS_SUCCESS.
1458 * Failure: NTSTATUS code.
1459 */
1460 NTSTATUS WINAPI
1461 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1462 {
1463 NTSTATUS Status;
1464 OBJECT_ATTRIBUTES ObjectAttributes;
1465 HANDLE ProcessToken;
1466 HANDLE ImpersonationToken;
1467
1468 TRACE("(%08x)\n", ImpersonationLevel);
1469
1470 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1471 &ProcessToken);
1472 if (Status != STATUS_SUCCESS)
1473 return Status;
1474
1475 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1476
1477 Status = NtDuplicateToken( ProcessToken,
1478 TOKEN_IMPERSONATE,
1479 &ObjectAttributes,
1480 ImpersonationLevel,
1481 TokenImpersonation,
1482 &ImpersonationToken );
1483 if (Status != STATUS_SUCCESS)
1484 {
1485 NtClose( ProcessToken );
1486 return Status;
1487 }
1488
1489 Status = NtSetInformationThread( GetCurrentThread(),
1490 ThreadImpersonationToken,
1491 &ImpersonationToken,
1492 sizeof(ImpersonationToken) );
1493
1494 NtClose( ImpersonationToken );
1495 NtClose( ProcessToken );
1496
1497 return Status;
1498 }
1499
1500 /******************************************************************************
1501 * NtAccessCheck [NTDLL.@]
1502 * ZwAccessCheck [NTDLL.@]
1503 *
1504 * Checks that a user represented by a token is allowed to access an object
1505 * represented by a security descriptor.
1506 *
1507 * PARAMS
1508 * SecurityDescriptor [I] The security descriptor of the object to check.
1509 * ClientToken [I] Token of the user accessing the object.
1510 * DesiredAccess [I] The desired access to the object.
1511 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1512 * PrivilegeSet [I/O] Privileges used during the access check.
1513 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1514 * GrantedAccess [O] The actual access rights granted.
1515 * AccessStatus [O] The status of the access check.
1516 *
1517 * RETURNS
1518 * NTSTATUS code.
1519 *
1520 * NOTES
1521 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1522 * the maximum access rights allowed by the SD and returns them in
1523 * GrantedAccess.
1524 * The SecurityDescriptor must have a valid owner and groups present,
1525 * otherwise the function will fail.
1526 */
1527 NTSTATUS WINAPI
1528 NtAccessCheck(
1529 PSECURITY_DESCRIPTOR SecurityDescriptor,
1530 HANDLE ClientToken,
1531 ACCESS_MASK DesiredAccess,
1532 PGENERIC_MAPPING GenericMapping,
1533 PPRIVILEGE_SET PrivilegeSet,
1534 PULONG ReturnLength,
1535 PULONG GrantedAccess,
1536 NTSTATUS *AccessStatus)
1537 {
1538 NTSTATUS status;
1539
1540 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1541 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1542 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1543
1544 SERVER_START_REQ( access_check )
1545 {
1546 struct security_descriptor sd;
1547 PSID owner;
1548 PSID group;
1549 PACL sacl;
1550 PACL dacl;
1551 BOOLEAN defaulted, present;
1552 DWORD revision;
1553 SECURITY_DESCRIPTOR_CONTROL control;
1554
1555 req->handle = ClientToken;
1556 req->desired_access = DesiredAccess;
1557 req->mapping_read = GenericMapping->GenericRead;
1558 req->mapping_write = GenericMapping->GenericWrite;
1559 req->mapping_execute = GenericMapping->GenericExecute;
1560 req->mapping_all = GenericMapping->GenericAll;
1561
1562 /* marshal security descriptor */
1563 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1564 sd.control = control & ~SE_SELF_RELATIVE;
1565 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1566 sd.owner_len = RtlLengthSid( owner );
1567 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1568 sd.group_len = RtlLengthSid( group );
1569 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1570 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1571 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1572 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1573
1574 wine_server_add_data( req, &sd, sizeof(sd) );
1575 wine_server_add_data( req, owner, sd.owner_len );
1576 wine_server_add_data( req, group, sd.group_len );
1577 wine_server_add_data( req, sacl, sd.sacl_len );
1578 wine_server_add_data( req, dacl, sd.dacl_len );
1579
1580 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1581
1582 status = wine_server_call( req );
1583
1584 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1585 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1586
1587 if (status == STATUS_SUCCESS)
1588 {
1589 *AccessStatus = reply->access_status;
1590 *GrantedAccess = reply->access_granted;
1591 }
1592 }
1593 SERVER_END_REQ;
1594
1595 return status;
1596 }
1597
1598 /******************************************************************************
1599 * NtSetSecurityObject [NTDLL.@]
1600 * ZwSetSecurityObject [NTDLL.@]
1601 *
1602 * Sets specified parts of the object's security descriptor.
1603 *
1604 * PARAMS
1605 * Handle [I] Handle to the object to change security descriptor of.
1606 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1607 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1608 *
1609 * RETURNS
1610 * NTSTATUS code.
1611 *
1612 */
1613 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1614 SECURITY_INFORMATION SecurityInformation,
1615 PSECURITY_DESCRIPTOR SecurityDescriptor)
1616 {
1617 NTSTATUS status;
1618 struct security_descriptor sd;
1619 PACL dacl = NULL, sacl = NULL;
1620 PSID owner = NULL, group = NULL;
1621 BOOLEAN defaulted, present;
1622 DWORD revision;
1623 SECURITY_DESCRIPTOR_CONTROL control;
1624
1625 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1626
1627 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1628
1629 memset( &sd, 0, sizeof(sd) );
1630 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1631 if (status != STATUS_SUCCESS) return status;
1632 sd.control = control & ~SE_SELF_RELATIVE;
1633
1634 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1635 {
1636 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1637 if (status != STATUS_SUCCESS) return status;
1638 if (!(sd.owner_len = RtlLengthSid( owner )))
1639 return STATUS_INVALID_SECURITY_DESCR;
1640 }
1641
1642 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1643 {
1644 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1645 if (status != STATUS_SUCCESS) return status;
1646 if (!(sd.group_len = RtlLengthSid( group )))
1647 return STATUS_INVALID_SECURITY_DESCR;
1648 }
1649
1650 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1651 {
1652 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1653 if (status != STATUS_SUCCESS) return status;
1654 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1655 sd.control |= SE_SACL_PRESENT;
1656 }
1657
1658 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1659 {
1660 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1661 if (status != STATUS_SUCCESS) return status;
1662 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1663 sd.control |= SE_DACL_PRESENT;
1664 }
1665
1666 SERVER_START_REQ( set_security_object )
1667 {
1668 req->handle = Handle;
1669 req->security_info = SecurityInformation;
1670
1671 wine_server_add_data( req, &sd, sizeof(sd) );
1672 wine_server_add_data( req, owner, sd.owner_len );
1673 wine_server_add_data( req, group, sd.group_len );
1674 wine_server_add_data( req, sacl, sd.sacl_len );
1675 wine_server_add_data( req, dacl, sd.dacl_len );
1676 status = wine_server_call( req );
1677 }
1678 SERVER_END_REQ;
1679
1680 return status;
1681 }
1682
1683 /******************************************************************************
1684 * RtlConvertSidToUnicodeString (NTDLL.@)
1685 *
1686 * The returned SID is used to access the USER registry hive usually
1687 *
1688 * the native function returns something like
1689 * "S-1-5-21-0000000000-000000000-0000000000-500";
1690 */
1691 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1692 PUNICODE_STRING String,
1693 PSID pSid,
1694 BOOLEAN AllocateString)
1695 {
1696 static const WCHAR formatW[] = {'-','%','u',0};
1697 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1698 WCHAR *p = buffer;
1699 const SID *sid = (const SID *)pSid;
1700 DWORD i, len;
1701
1702 *p++ = 'S';
1703 p += sprintfW( p, formatW, sid->Revision );
1704 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1705 sid->IdentifierAuthority.Value[4] ),
1706 MAKEWORD( sid->IdentifierAuthority.Value[3],
1707 sid->IdentifierAuthority.Value[2] )));
1708 for (i = 0; i < sid->SubAuthorityCount; i++)
1709 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1710
1711 len = (p + 1 - buffer) * sizeof(WCHAR);
1712
1713 String->Length = len - sizeof(WCHAR);
1714 if (AllocateString)
1715 {
1716 String->MaximumLength = len;
1717 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1718 return STATUS_NO_MEMORY;
1719 }
1720 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1721
1722 memcpy( String->Buffer, buffer, len );
1723 return STATUS_SUCCESS;
1724 }
1725
1726 /******************************************************************************
1727 * RtlQueryInformationAcl (NTDLL.@)
1728 */
1729 NTSTATUS WINAPI RtlQueryInformationAcl(
1730 PACL pAcl,
1731 LPVOID pAclInformation,
1732 DWORD nAclInformationLength,
1733 ACL_INFORMATION_CLASS dwAclInformationClass)
1734 {
1735 NTSTATUS status = STATUS_SUCCESS;
1736
1737 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1738 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1739
1740 switch (dwAclInformationClass)
1741 {
1742 case AclRevisionInformation:
1743 {
1744 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1745
1746 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1747 status = STATUS_INVALID_PARAMETER;
1748 else
1749 paclrev->AclRevision = pAcl->AclRevision;
1750
1751 break;
1752 }
1753
1754 case AclSizeInformation:
1755 {
1756 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1757
1758 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1759 status = STATUS_INVALID_PARAMETER;
1760 else
1761 {
1762 paclsize->AceCount = pAcl->AceCount;
1763 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1764 if (pAcl->AclSize < paclsize->AclBytesInUse)
1765 {
1766 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1767 paclsize->AclBytesFree = 0;
1768 paclsize->AclBytesInUse = pAcl->AclSize;
1769 }
1770 else
1771 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1772 }
1773
1774 break;
1775 }
1776
1777 default:
1778 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1779 status = STATUS_INVALID_PARAMETER;
1780 }
1781
1782 return status;
1783 }
1784
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.