[ATL] Add CString.AllocSysString
[reactos.git] / sdk / lib / rtl / security.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/rtl/security.c
5 * PURPOSE: Security related functions and Security Objects
6 * PROGRAMMER: Eric Kohl
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <rtl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS **********************************************************/
16
17 NTSTATUS
18 NTAPI
19 RtlpSetSecurityObject(IN PVOID Object OPTIONAL,
20 IN SECURITY_INFORMATION SecurityInformation,
21 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
22 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
23 IN ULONG AutoInheritFlags,
24 IN ULONG PoolType,
25 IN PGENERIC_MAPPING GenericMapping,
26 IN HANDLE Token OPTIONAL)
27 {
28 PISECURITY_DESCRIPTOR_RELATIVE pNewSd = NULL;
29 PSID pOwnerSid = NULL;
30 PSID pGroupSid = NULL;
31 PACL pDacl = NULL;
32 PACL pSacl = NULL;
33 BOOLEAN Defaulted;
34 BOOLEAN Present;
35 ULONG ulOwnerSidSize = 0, ulGroupSidSize = 0;
36 ULONG ulDaclSize = 0, ulSaclSize = 0;
37 ULONG ulNewSdSize;
38 SECURITY_DESCRIPTOR_CONTROL Control = SE_SELF_RELATIVE;
39 PUCHAR pDest;
40 NTSTATUS Status = STATUS_SUCCESS;
41
42 DPRINT("RtlpSetSecurityObject()\n");
43
44 /* Change the Owner SID */
45 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
46 {
47 Status = RtlGetOwnerSecurityDescriptor(ModificationDescriptor, &pOwnerSid, &Defaulted);
48 if (!NT_SUCCESS(Status))
49 return Status;
50 }
51 else
52 {
53 Status = RtlGetOwnerSecurityDescriptor(*ObjectsSecurityDescriptor, &pOwnerSid, &Defaulted);
54 if (!NT_SUCCESS(Status))
55 return Status;
56 }
57
58 if (pOwnerSid == NULL || !RtlValidSid(pOwnerSid))
59 return STATUS_INVALID_OWNER;
60
61 ulOwnerSidSize = RtlLengthSid(pOwnerSid);
62
63 /* Change the Group SID */
64 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
65 {
66 Status = RtlGetGroupSecurityDescriptor(ModificationDescriptor, &pGroupSid, &Defaulted);
67 if (!NT_SUCCESS(Status))
68 return Status;
69 }
70 else
71 {
72 Status = RtlGetGroupSecurityDescriptor(*ObjectsSecurityDescriptor, &pGroupSid, &Defaulted);
73 if (!NT_SUCCESS(Status))
74 return Status;
75 }
76
77 if (pGroupSid == NULL || !RtlValidSid(pGroupSid))
78 return STATUS_INVALID_PRIMARY_GROUP;
79
80 ulGroupSidSize = ROUND_UP(RtlLengthSid(pGroupSid), sizeof(ULONG));
81
82 /* Change the DACL */
83 if (SecurityInformation & DACL_SECURITY_INFORMATION)
84 {
85 Status = RtlGetDaclSecurityDescriptor(ModificationDescriptor, &Present, &pDacl, &Defaulted);
86 if (!NT_SUCCESS(Status))
87 return Status;
88
89 Control |= SE_DACL_PRESENT;
90 }
91 else
92 {
93 Status = RtlGetDaclSecurityDescriptor(*ObjectsSecurityDescriptor, &Present, &pDacl, &Defaulted);
94 if (!NT_SUCCESS(Status))
95 return Status;
96
97 if (Present)
98 Control |= SE_DACL_PRESENT;
99
100 if (Defaulted)
101 Control |= SE_DACL_DEFAULTED;
102 }
103
104 if (pDacl != NULL)
105 ulDaclSize = pDacl->AclSize;
106
107 /* Change the SACL */
108 if (SecurityInformation & SACL_SECURITY_INFORMATION)
109 {
110 Status = RtlGetSaclSecurityDescriptor(ModificationDescriptor, &Present, &pSacl, &Defaulted);
111 if (!NT_SUCCESS(Status))
112 return Status;
113
114 Control |= SE_SACL_PRESENT;
115 }
116 else
117 {
118 Status = RtlGetSaclSecurityDescriptor(*ObjectsSecurityDescriptor, &Present, &pSacl, &Defaulted);
119 if (!NT_SUCCESS(Status))
120 return Status;
121
122 if (Present)
123 Control |= SE_SACL_PRESENT;
124
125 if (Defaulted)
126 Control |= SE_SACL_DEFAULTED;
127 }
128
129 if (pSacl != NULL)
130 ulSaclSize = pSacl->AclSize;
131
132 /* Calculate the size of the new security descriptor */
133 ulNewSdSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
134 ROUND_UP(ulOwnerSidSize, sizeof(ULONG)) +
135 ROUND_UP(ulGroupSidSize, sizeof(ULONG)) +
136 ROUND_UP(ulDaclSize, sizeof(ULONG)) +
137 ROUND_UP(ulSaclSize, sizeof(ULONG));
138
139 /* Allocate the new security descriptor */
140 pNewSd = RtlAllocateHeap(RtlGetProcessHeap(), 0, ulNewSdSize);
141 if (pNewSd == NULL)
142 {
143 Status = STATUS_NO_MEMORY;
144 DPRINT1("New security descriptor allocation failed (Status 0x%08lx)\n", Status);
145 goto done;
146 }
147
148 /* Initialize the new security descriptor */
149 Status = RtlCreateSecurityDescriptorRelative(pNewSd, SECURITY_DESCRIPTOR_REVISION);
150 if (!NT_SUCCESS(Status))
151 {
152 DPRINT1("New security descriptor creation failed (Status 0x%08lx)\n", Status);
153 goto done;
154 }
155
156 /* Set the security descriptor control flags */
157 pNewSd->Control = Control;
158
159 pDest = (PUCHAR)((ULONG_PTR)pNewSd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
160
161 /* Copy the SACL */
162 if (pSacl != NULL)
163 {
164 RtlCopyMemory(pDest, pSacl, ulSaclSize);
165 pNewSd->Sacl = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd;
166 pDest = pDest + ROUND_UP(ulSaclSize, sizeof(ULONG));
167 }
168
169 /* Copy the DACL */
170 if (pDacl != NULL)
171 {
172 RtlCopyMemory(pDest, pDacl, ulDaclSize);
173 pNewSd->Dacl = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd;
174 pDest = pDest + ROUND_UP(ulDaclSize, sizeof(ULONG));
175 }
176
177 /* Copy the Owner SID */
178 RtlCopyMemory(pDest, pOwnerSid, ulOwnerSidSize);
179 pNewSd->Owner = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd;
180 pDest = pDest + ROUND_UP(ulOwnerSidSize, sizeof(ULONG));
181
182 /* Copy the Group SID */
183 RtlCopyMemory(pDest, pGroupSid, ulGroupSidSize);
184 pNewSd->Group = (ULONG_PTR)pDest - (ULONG_PTR)pNewSd;
185
186 /* Free the old security descriptor */
187 RtlFreeHeap(RtlGetProcessHeap(), 0, (PVOID)*ObjectsSecurityDescriptor);
188
189 /* Return the new security descriptor */
190 *ObjectsSecurityDescriptor = (PSECURITY_DESCRIPTOR)pNewSd;
191
192 done:
193 if (!NT_SUCCESS(Status))
194 {
195 if (pNewSd != NULL)
196 RtlFreeHeap(RtlGetProcessHeap(), 0, pNewSd);
197 }
198
199 return Status;
200 }
201
202 NTSTATUS
203 NTAPI
204 RtlpNewSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor,
205 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
206 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
207 IN LPGUID *ObjectTypes,
208 IN ULONG GuidCount,
209 IN BOOLEAN IsDirectoryObject,
210 IN ULONG AutoInheritFlags,
211 IN HANDLE Token,
212 IN PGENERIC_MAPPING GenericMapping)
213 {
214 UNIMPLEMENTED;
215 return STATUS_NOT_IMPLEMENTED;
216 }
217
218 NTSTATUS
219 NTAPI
220 RtlpConvertToAutoInheritSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor,
221 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
222 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
223 IN LPGUID ObjectType,
224 IN BOOLEAN IsDirectoryObject,
225 IN PGENERIC_MAPPING GenericMapping)
226 {
227 UNIMPLEMENTED;
228 return STATUS_NOT_IMPLEMENTED;
229 }
230
231 /* PUBLIC FUNCTIONS ***********************************************************/
232
233 /*
234 * @implemented
235 */
236 NTSTATUS
237 NTAPI
238 RtlDefaultNpAcl(OUT PACL *pAcl)
239 {
240 NTSTATUS Status;
241 HANDLE TokenHandle;
242 PTOKEN_OWNER OwnerSid;
243 ULONG ReturnLength = 0;
244 ULONG AclSize;
245 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
246 SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
247
248 /*
249 * Temporary buffer large enough to hold a maximum of two SIDs.
250 * An alternative is to call RtlAllocateAndInitializeSid many times...
251 */
252 UCHAR SidBuffer[16];
253 PSID Sid = (PSID)&SidBuffer;
254
255 ASSERT(RtlLengthRequiredSid(2) == 16);
256
257 /* Initialize the user ACL pointer */
258 *pAcl = NULL;
259
260 /*
261 * Try to retrieve the SID of the current owner. For that,
262 * we first attempt to get the current thread level token.
263 */
264 Status = NtOpenThreadToken(NtCurrentThread(),
265 TOKEN_QUERY,
266 TRUE,
267 &TokenHandle);
268 if (Status == STATUS_NO_TOKEN)
269 {
270 /*
271 * No thread level token, so use the process level token.
272 * This is the common case since the only time a thread
273 * has a token is when it is impersonating.
274 */
275 Status = NtOpenProcessToken(NtCurrentProcess(),
276 TOKEN_QUERY,
277 &TokenHandle);
278 }
279 /* Fail if we didn't succeed in retrieving a handle to the token */
280 if (!NT_SUCCESS(Status)) return Status;
281
282 /*
283 * Retrieve the owner SID from the token.
284 */
285
286 /* Query the needed size... */
287 Status = NtQueryInformationToken(TokenHandle,
288 TokenOwner,
289 NULL, 0,
290 &ReturnLength);
291 /* ... so that we must fail with STATUS_BUFFER_TOO_SMALL error */
292 if (Status != STATUS_BUFFER_TOO_SMALL) goto Cleanup1;
293
294 /* Allocate space for the owner SID */
295 OwnerSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, ReturnLength);
296 if (OwnerSid == NULL)
297 {
298 Status = STATUS_NO_MEMORY;
299 goto Cleanup1;
300 }
301
302 /* Retrieve the owner SID; we must succeed */
303 Status = NtQueryInformationToken(TokenHandle,
304 TokenOwner,
305 OwnerSid,
306 ReturnLength,
307 &ReturnLength);
308 if (!NT_SUCCESS(Status)) goto Cleanup2;
309
310 /*
311 * Allocate one ACL with 5 ACEs.
312 *
313 * NOTE: sizeof(ACE) == sizeof(ACCESS_ALLOWED_ACE) - sizeof(((ACCESS_ALLOWED_ACE*)NULL)->SidStart)
314 * (see kernel32/client/debugger.c line 54).
315 */
316 AclSize = sizeof(ACL) + // Header
317 5 * sizeof(ACE /*ACCESS_ALLOWED_ACE*/) + // 5 ACEs:
318 RtlLengthRequiredSid(1) + // LocalSystem
319 RtlLengthRequiredSid(2) + // Administrators
320 RtlLengthRequiredSid(1) + // Anonymous
321 RtlLengthRequiredSid(1) + // World
322 RtlLengthSid(OwnerSid->Owner); // Owner
323
324 *pAcl = RtlAllocateHeap(RtlGetProcessHeap(), 0, AclSize);
325 if (*pAcl == NULL)
326 {
327 Status = STATUS_NO_MEMORY;
328 goto Cleanup2;
329 }
330
331 /*
332 * Build the ACL and add the five ACEs.
333 */
334 Status = RtlCreateAcl(*pAcl, AclSize, ACL_REVISION2);
335 ASSERT(NT_SUCCESS(Status));
336
337 /* Local System SID - Generic All */
338 Status = RtlInitializeSid(Sid, &NtAuthority, 1);
339 ASSERT(NT_SUCCESS(Status));
340 *RtlSubAuthoritySid(Sid, 0) = SECURITY_LOCAL_SYSTEM_RID;
341 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_ALL, Sid);
342 ASSERT(NT_SUCCESS(Status));
343
344 /* Administrators SID - Generic All */
345 Status = RtlInitializeSid(Sid, &NtAuthority, 2);
346 ASSERT(NT_SUCCESS(Status));
347 *RtlSubAuthoritySid(Sid, 0) = SECURITY_BUILTIN_DOMAIN_RID;
348 *RtlSubAuthoritySid(Sid, 1) = DOMAIN_ALIAS_RID_ADMINS;
349 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_ALL, Sid);
350 ASSERT(NT_SUCCESS(Status));
351
352 /* Owner SID - Generic All */
353 RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_ALL, OwnerSid->Owner);
354 ASSERT(NT_SUCCESS(Status));
355
356 /* Anonymous SID - Generic Read */
357 Status = RtlInitializeSid(Sid, &NtAuthority, 1);
358 ASSERT(NT_SUCCESS(Status));
359 *RtlSubAuthoritySid(Sid, 0) = SECURITY_ANONYMOUS_LOGON_RID;
360 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_READ, Sid);
361 ASSERT(NT_SUCCESS(Status));
362
363 /* World SID - Generic Read */
364 Status = RtlInitializeSid(Sid, &WorldAuthority, 1);
365 ASSERT(NT_SUCCESS(Status));
366 *RtlSubAuthoritySid(Sid, 0) = SECURITY_WORLD_RID;
367 Status = RtlAddAccessAllowedAce(*pAcl, ACL_REVISION2, GENERIC_READ, Sid);
368 ASSERT(NT_SUCCESS(Status));
369
370 /* If some problem happened, cleanup everything */
371 if (!NT_SUCCESS(Status))
372 {
373 RtlFreeHeap(RtlGetProcessHeap(), 0, *pAcl);
374 *pAcl = NULL;
375 }
376
377 Cleanup2:
378 /* Get rid of the owner SID */
379 RtlFreeHeap(RtlGetProcessHeap(), 0, OwnerSid);
380
381 Cleanup1:
382 /* Close the token handle */
383 NtClose(TokenHandle);
384
385 /* Done */
386 return Status;
387 }
388
389 /*
390 * @unimplemented
391 */
392 NTSTATUS
393 NTAPI
394 RtlCreateAndSetSD(IN PVOID AceData,
395 IN ULONG AceCount,
396 IN PSID OwnerSid OPTIONAL,
397 IN PSID GroupSid OPTIONAL,
398 OUT PSECURITY_DESCRIPTOR *NewDescriptor)
399 {
400 UNIMPLEMENTED;
401 return STATUS_NOT_IMPLEMENTED;
402 }
403
404 /*
405 * @implemented
406 */
407 NTSTATUS
408 NTAPI
409 RtlDeleteSecurityObject(IN PSECURITY_DESCRIPTOR *ObjectDescriptor)
410 {
411 DPRINT1("RtlDeleteSecurityObject(%p)\n", ObjectDescriptor);
412
413 /* Free the object from the heap */
414 RtlFreeHeap(RtlGetProcessHeap(), 0, *ObjectDescriptor);
415 return STATUS_SUCCESS;
416 }
417
418 /*
419 * @implemented
420 */
421 NTSTATUS
422 NTAPI
423 RtlNewSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor,
424 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
425 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
426 IN BOOLEAN IsDirectoryObject,
427 IN HANDLE Token,
428 IN PGENERIC_MAPPING GenericMapping)
429 {
430 DPRINT1("RtlNewSecurityObject(%p)\n", ParentDescriptor);
431
432 /* Call the internal API */
433 return RtlpNewSecurityObject(ParentDescriptor,
434 CreatorDescriptor,
435 NewDescriptor,
436 NULL,
437 0,
438 IsDirectoryObject,
439 0,
440 Token,
441 GenericMapping);
442 }
443
444 /*
445 * @implemented
446 */
447 NTSTATUS
448 NTAPI
449 RtlNewSecurityObjectEx(IN PSECURITY_DESCRIPTOR ParentDescriptor,
450 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
451 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
452 IN LPGUID ObjectType,
453 IN BOOLEAN IsDirectoryObject,
454 IN ULONG AutoInheritFlags,
455 IN HANDLE Token,
456 IN PGENERIC_MAPPING GenericMapping)
457 {
458 DPRINT1("RtlNewSecurityObjectEx(%p)\n", ParentDescriptor);
459
460 /* Call the internal API */
461 return RtlpNewSecurityObject(ParentDescriptor,
462 CreatorDescriptor,
463 NewDescriptor,
464 ObjectType ? &ObjectType : NULL,
465 ObjectType ? 1 : 0,
466 IsDirectoryObject,
467 AutoInheritFlags,
468 Token,
469 GenericMapping);
470 }
471
472 /*
473 * @implemented
474 */
475 NTSTATUS
476 NTAPI
477 RtlNewSecurityObjectWithMultipleInheritance(IN PSECURITY_DESCRIPTOR ParentDescriptor,
478 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
479 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
480 IN LPGUID *ObjectTypes,
481 IN ULONG GuidCount,
482 IN BOOLEAN IsDirectoryObject,
483 IN ULONG AutoInheritFlags,
484 IN HANDLE Token,
485 IN PGENERIC_MAPPING GenericMapping)
486 {
487 DPRINT1("RtlNewSecurityObjectWithMultipleInheritance(%p)\n", ParentDescriptor);
488
489 /* Call the internal API */
490 return RtlpNewSecurityObject(ParentDescriptor,
491 CreatorDescriptor,
492 NewDescriptor,
493 ObjectTypes,
494 GuidCount,
495 IsDirectoryObject,
496 AutoInheritFlags,
497 Token,
498 GenericMapping);
499 }
500
501 /*
502 * @implemented
503 */
504 NTSTATUS
505 NTAPI
506 RtlNewInstanceSecurityObject(IN BOOLEAN ParentDescriptorChanged,
507 IN BOOLEAN CreatorDescriptorChanged,
508 IN PLUID OldClientTokenModifiedId,
509 OUT PLUID NewClientTokenModifiedId,
510 IN PSECURITY_DESCRIPTOR ParentDescriptor,
511 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
512 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
513 IN BOOLEAN IsDirectoryObject,
514 IN HANDLE Token,
515 IN PGENERIC_MAPPING GenericMapping)
516 {
517 TOKEN_STATISTICS TokenStats;
518 ULONG Size;
519 NTSTATUS Status;
520 DPRINT1("RtlNewInstanceSecurityObject(%p)\n", ParentDescriptor);
521
522 /* Query the token statistics */
523 Status = NtQueryInformationToken(Token,
524 TokenStatistics,
525 &TokenStats,
526 sizeof(TokenStats),
527 &Size);
528 if (!NT_SUCCESS(Status)) return Status;
529
530 /* Return the LUID */
531 *NewClientTokenModifiedId = TokenStats.ModifiedId;
532
533 /* Check if the LUID changed */
534 if (RtlEqualLuid(NewClientTokenModifiedId, OldClientTokenModifiedId))
535 {
536 /* Did nothing change? */
537 if (!(ParentDescriptorChanged) && !(CreatorDescriptorChanged))
538 {
539 /* There's no new descriptor, we're done */
540 *NewDescriptor = NULL;
541 return STATUS_SUCCESS;
542 }
543 }
544
545 /* Call the standard API */
546 return RtlNewSecurityObject(ParentDescriptor,
547 CreatorDescriptor,
548 NewDescriptor,
549 IsDirectoryObject,
550 Token,
551 GenericMapping);
552 }
553
554 /*
555 * @implemented
556 */
557 NTSTATUS
558 NTAPI
559 RtlCreateUserSecurityObject(IN PVOID AceData,
560 IN ULONG AceCount,
561 IN PSID OwnerSid,
562 IN PSID GroupSid,
563 IN BOOLEAN IsDirectoryObject,
564 IN PGENERIC_MAPPING GenericMapping,
565 OUT PSECURITY_DESCRIPTOR *NewDescriptor)
566 {
567 NTSTATUS Status;
568 PSECURITY_DESCRIPTOR Sd;
569 HANDLE TokenHandle;
570 DPRINT1("RtlCreateUserSecurityObject(%p)\n", AceData);
571
572 /* Create the security descriptor based on the ACE Data */
573 Status = RtlCreateAndSetSD(AceData,
574 AceCount,
575 OwnerSid,
576 GroupSid,
577 &Sd);
578 if (!NT_SUCCESS(Status)) return Status;
579
580 /* Open the process token */
581 Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY, &TokenHandle);
582 if (!NT_SUCCESS(Status)) goto Quickie;
583
584 /* Create the security object */
585 Status = RtlNewSecurityObject(NULL,
586 Sd,
587 NewDescriptor,
588 IsDirectoryObject,
589 TokenHandle,
590 GenericMapping);
591
592 /* We're done, close the token handle */
593 NtClose(TokenHandle);
594
595 Quickie:
596 /* Free the SD and return status */
597 RtlFreeHeap(RtlGetProcessHeap(), 0, Sd);
598 return Status;
599 }
600
601 /*
602 * @implemented
603 */
604 NTSTATUS
605 NTAPI
606 RtlNewSecurityGrantedAccess(IN ACCESS_MASK DesiredAccess,
607 OUT PPRIVILEGE_SET Privileges,
608 IN OUT PULONG Length,
609 IN HANDLE Token,
610 IN PGENERIC_MAPPING GenericMapping,
611 OUT PACCESS_MASK RemainingDesiredAccess)
612 {
613 NTSTATUS Status;
614 BOOLEAN Granted, CallerToken;
615 TOKEN_STATISTICS TokenStats;
616 ULONG Size;
617 DPRINT1("RtlNewSecurityGrantedAccess(%lx)\n", DesiredAccess);
618
619 /* Has the caller passed a token? */
620 if (!Token)
621 {
622 /* Remember that we'll have to close the handle */
623 CallerToken = FALSE;
624
625 /* Nope, open it */
626 Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, TRUE, &Token);
627 if (!NT_SUCCESS(Status)) return Status;
628 }
629 else
630 {
631 /* Yep, use it */
632 CallerToken = TRUE;
633 }
634
635 /* Get information on the token */
636 Status = NtQueryInformationToken(Token,
637 TokenStatistics,
638 &TokenStats,
639 sizeof(TokenStats),
640 &Size);
641 ASSERT(NT_SUCCESS(Status));
642
643 /* Windows doesn't do anything with the token statistics! */
644
645 /* Map the access and return it back decoded */
646 RtlMapGenericMask(&DesiredAccess, GenericMapping);
647 *RemainingDesiredAccess = DesiredAccess;
648
649 /* Check if one of the rights requested was the SACL right */
650 if (DesiredAccess & ACCESS_SYSTEM_SECURITY)
651 {
652 /* Pretend that it's allowed FIXME: Do privilege check */
653 DPRINT1("Missing privilege check for SE_SECURITY_PRIVILEGE");
654 Granted = TRUE;
655 *RemainingDesiredAccess &= ~ACCESS_SYSTEM_SECURITY;
656 }
657 else
658 {
659 /* Nothing to grant */
660 Granted = FALSE;
661 }
662
663 /* If the caller did not pass in a token, close the handle to ours */
664 if (!CallerToken) NtClose(Token);
665
666 /* We need space to return only 1 privilege -- already part of the struct */
667 Size = sizeof(PRIVILEGE_SET);
668 if (Size > *Length)
669 {
670 /* Tell the caller how much space we need and fail */
671 *Length = Size;
672 return STATUS_BUFFER_TOO_SMALL;
673 }
674
675 /* Check if the SACL right was granted... */
676 RtlZeroMemory(&Privileges, Size);
677 if (Granted)
678 {
679 /* Yes, return it in the structure */
680 Privileges->PrivilegeCount = 1;
681 Privileges->Privilege[0].Luid.LowPart = SE_SECURITY_PRIVILEGE;
682 Privileges->Privilege[0].Luid.HighPart = 0;
683 Privileges->Privilege[0].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;
684 }
685
686 /* All done */
687 return STATUS_SUCCESS;
688 }
689
690 /*
691 * @unimplemented
692 */
693 NTSTATUS
694 NTAPI
695 RtlQuerySecurityObject(IN PSECURITY_DESCRIPTOR ObjectDescriptor,
696 IN SECURITY_INFORMATION SecurityInformation,
697 OUT PSECURITY_DESCRIPTOR ResultantDescriptor,
698 IN ULONG DescriptorLength,
699 OUT PULONG ReturnLength)
700 {
701 NTSTATUS Status;
702 SECURITY_DESCRIPTOR desc;
703 BOOLEAN defaulted, present;
704 PACL pacl;
705 PSID psid;
706
707 Status = RtlCreateSecurityDescriptor(&desc, SECURITY_DESCRIPTOR_REVISION);
708 if (!NT_SUCCESS(Status)) return Status;
709
710 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
711 {
712 Status = RtlGetOwnerSecurityDescriptor(ObjectDescriptor, &psid, &defaulted);
713 if (!NT_SUCCESS(Status)) return Status;
714 Status = RtlSetOwnerSecurityDescriptor(&desc, psid, defaulted);
715 if (!NT_SUCCESS(Status)) return Status;
716 }
717
718 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
719 {
720 Status = RtlGetGroupSecurityDescriptor(ObjectDescriptor, &psid, &defaulted);
721 if (!NT_SUCCESS(Status)) return Status;
722 Status = RtlSetGroupSecurityDescriptor(&desc, psid, defaulted);
723 if (!NT_SUCCESS(Status)) return Status;
724 }
725
726 if (SecurityInformation & DACL_SECURITY_INFORMATION)
727 {
728 Status = RtlGetDaclSecurityDescriptor(ObjectDescriptor, &present, &pacl, &defaulted);
729 if (!NT_SUCCESS(Status)) return Status;
730 Status = RtlSetDaclSecurityDescriptor(&desc, present, pacl, defaulted);
731 if (!NT_SUCCESS(Status)) return Status;
732 }
733
734 if (SecurityInformation & SACL_SECURITY_INFORMATION)
735 {
736 Status = RtlGetSaclSecurityDescriptor(ObjectDescriptor, &present, &pacl, &defaulted);
737 if (!NT_SUCCESS(Status)) return Status;
738 Status = RtlSetSaclSecurityDescriptor(&desc, present, pacl, defaulted);
739 if (!NT_SUCCESS(Status)) return Status;
740 }
741
742 *ReturnLength = DescriptorLength;
743 return RtlAbsoluteToSelfRelativeSD(&desc, ResultantDescriptor, ReturnLength);
744 }
745
746
747 /*
748 * @implemented
749 */
750 NTSTATUS
751 NTAPI
752 RtlSetSecurityObject(IN SECURITY_INFORMATION SecurityInformation,
753 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
754 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
755 IN PGENERIC_MAPPING GenericMapping,
756 IN HANDLE Token OPTIONAL)
757 {
758 /* Call the internal API */
759 return RtlpSetSecurityObject(NULL,
760 SecurityInformation,
761 ModificationDescriptor,
762 ObjectsSecurityDescriptor,
763 0,
764 PagedPool,
765 GenericMapping,
766 Token);
767 }
768
769 /*
770 * @implemented
771 */
772 NTSTATUS
773 NTAPI
774 RtlSetSecurityObjectEx(IN SECURITY_INFORMATION SecurityInformation,
775 IN PSECURITY_DESCRIPTOR ModificationDescriptor,
776 IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor,
777 IN ULONG AutoInheritFlags,
778 IN PGENERIC_MAPPING GenericMapping,
779 IN HANDLE Token OPTIONAL)
780 {
781 /* Call the internal API */
782 return RtlpSetSecurityObject(NULL,
783 SecurityInformation,
784 ModificationDescriptor,
785 ObjectsSecurityDescriptor,
786 AutoInheritFlags,
787 PagedPool,
788 GenericMapping,
789 Token);
790
791 }
792
793 /*
794 * @implemented
795 */
796 NTSTATUS
797 NTAPI
798 RtlConvertToAutoInheritSecurityObject(IN PSECURITY_DESCRIPTOR ParentDescriptor,
799 IN PSECURITY_DESCRIPTOR CreatorDescriptor,
800 OUT PSECURITY_DESCRIPTOR *NewDescriptor,
801 IN LPGUID ObjectType,
802 IN BOOLEAN IsDirectoryObject,
803 IN PGENERIC_MAPPING GenericMapping)
804 {
805 /* Call the internal API */
806 return RtlpConvertToAutoInheritSecurityObject(ParentDescriptor,
807 CreatorDescriptor,
808 NewDescriptor,
809 ObjectType,
810 IsDirectoryObject,
811 GenericMapping);
812 }
813
814 /*
815 * @unimplemented
816 */
817 NTSTATUS
818 NTAPI
819 RtlRegisterSecureMemoryCacheCallback(IN PRTL_SECURE_MEMORY_CACHE_CALLBACK Callback)
820 {
821 UNIMPLEMENTED;
822 return STATUS_NOT_IMPLEMENTED;
823 }
824
825 /*
826 * @unimplemented
827 */
828 BOOLEAN
829 NTAPI
830 RtlFlushSecureMemoryCache(IN PVOID MemoryCache,
831 IN OPTIONAL SIZE_T MemoryLength)
832 {
833 UNIMPLEMENTED;
834 return FALSE;
835 }