1 /*
2 * ReactOS MARTA provider
3 * Copyright (C) 2005 - 2006 ReactOS Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 /*
20 * PROJECT: ReactOS MARTA provider
21 * FILE: lib/ntmarta/ntmarta.c
22 * PURPOSE: ReactOS MARTA provider
23 * PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
24 *
25 * UPDATE HISTORY:
26 * 07/26/2005 Created
27 */
28
29 #include "ntmarta.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 HINSTANCE hDllInstance;
35
36 /* FIXME: Vista+ API */
37 VOID
38 WINAPI
SetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,OUT LPDWORD DesiredAccess)39 SetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
40 OUT LPDWORD DesiredAccess)
41 {
42 *DesiredAccess = 0;
43
44 if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
45 *DesiredAccess |= WRITE_OWNER;
46
47 if (SecurityInformation & DACL_SECURITY_INFORMATION)
48 *DesiredAccess |= WRITE_DAC;
49
50 if (SecurityInformation & SACL_SECURITY_INFORMATION)
51 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
52 }
53
54 /* FIXME: Vista+ API */
55 VOID
56 WINAPI
QuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,OUT LPDWORD DesiredAccess)57 QuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
58 OUT LPDWORD DesiredAccess)
59 {
60 *DesiredAccess = 0;
61
62 if (SecurityInformation & (OWNER_SECURITY_INFORMATION |
63 GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION))
64 {
65 *DesiredAccess |= READ_CONTROL;
66 }
67
68 if (SecurityInformation & SACL_SECURITY_INFORMATION)
69 *DesiredAccess |= ACCESS_SYSTEM_SECURITY;
70 }
71
72 static ACCESS_MODE
AccpGetAceAccessMode(IN PACE_HEADER AceHeader)73 AccpGetAceAccessMode(IN PACE_HEADER AceHeader)
74 {
75 ACCESS_MODE Mode = NOT_USED_ACCESS;
76
77 switch (AceHeader->AceType)
78 {
79 case ACCESS_ALLOWED_ACE_TYPE:
80 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
81 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
82 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
83 Mode = GRANT_ACCESS;
84 break;
85
86 case ACCESS_DENIED_ACE_TYPE:
87 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
88 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
89 case ACCESS_DENIED_OBJECT_ACE_TYPE:
90 Mode = DENY_ACCESS;
91 break;
92
93 case SYSTEM_AUDIT_ACE_TYPE:
94 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
95 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
96 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
97 if (AceHeader->AceFlags & FAILED_ACCESS_ACE_FLAG)
98 Mode = SET_AUDIT_FAILURE;
99 else if (AceHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
100 Mode = SET_AUDIT_SUCCESS;
101 break;
102 }
103
104 return Mode;
105 }
106
107 static UINT
AccpGetAceStructureSize(IN PACE_HEADER AceHeader)108 AccpGetAceStructureSize(IN PACE_HEADER AceHeader)
109 {
110 UINT Size = 0;
111
112 switch (AceHeader->AceType)
113 {
114 case ACCESS_ALLOWED_ACE_TYPE:
115 case ACCESS_DENIED_ACE_TYPE:
116 Size = FIELD_OFFSET(ACCESS_ALLOWED_ACE,
117 SidStart);
118 break;
119 case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
120 case ACCESS_DENIED_CALLBACK_ACE_TYPE:
121 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_ACE,
122 SidStart);
123 break;
124 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
125 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
126 {
127 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
128 Size = FIELD_OFFSET(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE,
129 ObjectType);
130 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
131 Size += sizeof(Ace->ObjectType);
132 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
133 Size += sizeof(Ace->InheritedObjectType);
134 break;
135 }
136 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
137 case ACCESS_DENIED_OBJECT_ACE_TYPE:
138 {
139 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
140 Size = FIELD_OFFSET(ACCESS_ALLOWED_OBJECT_ACE,
141 ObjectType);
142 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
143 Size += sizeof(Ace->ObjectType);
144 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
145 Size += sizeof(Ace->InheritedObjectType);
146 break;
147 }
148
149 case SYSTEM_AUDIT_ACE_TYPE:
150 Size = FIELD_OFFSET(SYSTEM_AUDIT_ACE,
151 SidStart);
152 break;
153 case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
154 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_ACE,
155 SidStart);
156 break;
157 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
158 {
159 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
160 Size = FIELD_OFFSET(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE,
161 ObjectType);
162 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
163 Size += sizeof(Ace->ObjectType);
164 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
165 Size += sizeof(Ace->InheritedObjectType);
166 break;
167 }
168 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
169 {
170 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
171 Size = FIELD_OFFSET(SYSTEM_AUDIT_OBJECT_ACE,
172 ObjectType);
173 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
174 Size += sizeof(Ace->ObjectType);
175 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
176 Size += sizeof(Ace->InheritedObjectType);
177 break;
178 }
179
180 case SYSTEM_MANDATORY_LABEL_ACE_TYPE:
181 Size = FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE,
182 SidStart);
183 break;
184 }
185
186 return Size;
187 }
188
189 static PSID
AccpGetAceSid(IN PACE_HEADER AceHeader)190 AccpGetAceSid(IN PACE_HEADER AceHeader)
191 {
192 return (PSID)((ULONG_PTR)AceHeader + AccpGetAceStructureSize(AceHeader));
193 }
194
195 static ACCESS_MASK
AccpGetAceAccessMask(IN PACE_HEADER AceHeader)196 AccpGetAceAccessMask(IN PACE_HEADER AceHeader)
197 {
198 return *((PACCESS_MASK)(AceHeader + 1));
199 }
200
201 static BOOL
AccpIsObjectAce(IN PACE_HEADER AceHeader)202 AccpIsObjectAce(IN PACE_HEADER AceHeader)
203 {
204 BOOL Ret;
205
206 switch (AceHeader->AceType)
207 {
208 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
209 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
210 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
211 case ACCESS_DENIED_OBJECT_ACE_TYPE:
212 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
213 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
214 Ret = TRUE;
215 break;
216
217 default:
218 Ret = FALSE;
219 break;
220 }
221
222 return Ret;
223 }
224
225 static DWORD
AccpGetTrusteeObjects(IN PTRUSTEE_W Trustee,OUT GUID * pObjectTypeGuid OPTIONAL,OUT GUID * pInheritedObjectTypeGuid OPTIONAL)226 AccpGetTrusteeObjects(IN PTRUSTEE_W Trustee,
227 OUT GUID *pObjectTypeGuid OPTIONAL,
228 OUT GUID *pInheritedObjectTypeGuid OPTIONAL)
229 {
230 DWORD Ret;
231
232 switch (Trustee->TrusteeForm)
233 {
234 case TRUSTEE_IS_OBJECTS_AND_NAME:
235 {
236 POBJECTS_AND_NAME_W pOan = (POBJECTS_AND_NAME_W)Trustee->ptstrName;
237
238 /* pOan->ObjectsPresent should always be 0 here because a previous
239 call to AccpGetTrusteeSid should have rejected these trustees
240 already. */
241 ASSERT(pOan->ObjectsPresent == 0);
242
243 Ret = pOan->ObjectsPresent;
244 break;
245 }
246
247 case TRUSTEE_IS_OBJECTS_AND_SID:
248 {
249 POBJECTS_AND_SID pOas = (POBJECTS_AND_SID)Trustee->ptstrName;
250
251 if (pObjectTypeGuid != NULL && pOas->ObjectsPresent & ACE_OBJECT_TYPE_PRESENT)
252 *pObjectTypeGuid = pOas->ObjectTypeGuid;
253
254 if (pInheritedObjectTypeGuid != NULL && pOas->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT)
255 *pInheritedObjectTypeGuid = pOas->InheritedObjectTypeGuid;
256
257 Ret = pOas->ObjectsPresent;
258 break;
259 }
260
261 default:
262 /* Any other trustee forms have no objects attached... */
263 Ret = 0;
264 break;
265 }
266
267 return Ret;
268 }
269
270 static DWORD
AccpCalcNeededAceSize(IN PSID Sid,IN DWORD ObjectsPresent)271 AccpCalcNeededAceSize(IN PSID Sid,
272 IN DWORD ObjectsPresent)
273 {
274 DWORD Ret;
275
276 Ret = sizeof(ACE) + GetLengthSid(Sid);
277
278 /* This routine calculates the generic size of the ACE needed.
279 If no objects are present it is assumed that only a standard
280 ACE is to be created. */
281
282 if (ObjectsPresent & ACE_OBJECT_TYPE_PRESENT)
283 Ret += sizeof(GUID);
284 if (ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT)
285 Ret += sizeof(GUID);
286
287 if (ObjectsPresent != 0)
288 Ret += sizeof(DWORD); /* Include the Flags member to make it an object ACE */
289
290 return Ret;
291 }
292
293 static GUID*
AccpGetObjectAceObjectType(IN PACE_HEADER AceHeader)294 AccpGetObjectAceObjectType(IN PACE_HEADER AceHeader)
295 {
296 GUID *ObjectType = NULL;
297
298 switch (AceHeader->AceType)
299 {
300 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
301 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
302 {
303 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
304 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
305 ObjectType = &Ace->ObjectType;
306 break;
307 }
308 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
309 case ACCESS_DENIED_OBJECT_ACE_TYPE:
310 {
311 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
312 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
313 ObjectType = &Ace->ObjectType;
314 break;
315 }
316
317 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
318 {
319 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
320 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
321 ObjectType = &Ace->ObjectType;
322 break;
323 }
324 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
325 {
326 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
327 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
328 ObjectType = &Ace->ObjectType;
329 break;
330 }
331 }
332
333 return ObjectType;
334 }
335
336 static GUID*
AccpGetObjectAceInheritedObjectType(IN PACE_HEADER AceHeader)337 AccpGetObjectAceInheritedObjectType(IN PACE_HEADER AceHeader)
338 {
339 GUID *ObjectType = NULL;
340
341 switch (AceHeader->AceType)
342 {
343 case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
344 case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
345 {
346 PACCESS_ALLOWED_CALLBACK_OBJECT_ACE Ace = (PACCESS_ALLOWED_CALLBACK_OBJECT_ACE)AceHeader;
347 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
348 {
349 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
350 ObjectType = &Ace->InheritedObjectType;
351 else
352 ObjectType = &Ace->ObjectType;
353 }
354 break;
355 }
356 case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
357 case ACCESS_DENIED_OBJECT_ACE_TYPE:
358 {
359 PACCESS_ALLOWED_OBJECT_ACE Ace = (PACCESS_ALLOWED_OBJECT_ACE)AceHeader;
360 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
361 {
362 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
363 ObjectType = &Ace->InheritedObjectType;
364 else
365 ObjectType = &Ace->ObjectType;
366 }
367 break;
368 }
369
370 case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
371 {
372 PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE Ace = (PSYSTEM_AUDIT_CALLBACK_OBJECT_ACE)AceHeader;
373 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
374 {
375 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
376 ObjectType = &Ace->InheritedObjectType;
377 else
378 ObjectType = &Ace->ObjectType;
379 }
380 break;
381 }
382 case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
383 {
384 PSYSTEM_AUDIT_OBJECT_ACE Ace = (PSYSTEM_AUDIT_OBJECT_ACE)AceHeader;
385 if (Ace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
386 {
387 if (Ace->Flags & ACE_OBJECT_TYPE_PRESENT)
388 ObjectType = &Ace->InheritedObjectType;
389 else
390 ObjectType = &Ace->ObjectType;
391 }
392 break;
393 }
394 }
395
396 return ObjectType;
397 }
398
399 static DWORD
AccpOpenLSAPolicyHandle(IN LPWSTR SystemName,IN ACCESS_MASK DesiredAccess,OUT PLSA_HANDLE pPolicyHandle)400 AccpOpenLSAPolicyHandle(IN LPWSTR SystemName,
401 IN ACCESS_MASK DesiredAccess,
402 OUT PLSA_HANDLE pPolicyHandle)
403 {
404 LSA_OBJECT_ATTRIBUTES LsaObjectAttributes = {0};
405 LSA_UNICODE_STRING LsaSystemName, *psn;
406 SIZE_T SystemNameLength;
407 NTSTATUS Status;
408
409 if (SystemName != NULL && SystemName[0] != L'\0')
410 {
411 SystemNameLength = wcslen(SystemName);
412 if (SystemNameLength > UNICODE_STRING_MAX_CHARS)
413 {
414 return ERROR_INVALID_PARAMETER;
415 }
416
417 LsaSystemName.Buffer = SystemName;
418 LsaSystemName.Length = (USHORT)SystemNameLength * sizeof(WCHAR);
419 LsaSystemName.MaximumLength = LsaSystemName.Length + sizeof(WCHAR);
420 psn = &LsaSystemName;
421 }
422 else
423 {
424 psn = NULL;
425 }
426
427 Status = LsaOpenPolicy(psn,
428 &LsaObjectAttributes,
429 DesiredAccess,
430 pPolicyHandle);
431 if (!NT_SUCCESS(Status))
432 return LsaNtStatusToWinError(Status);
433
434 return ERROR_SUCCESS;
435 }
436
437 static LPWSTR
AccpGetTrusteeName(IN PTRUSTEE_W Trustee)438 AccpGetTrusteeName(IN PTRUSTEE_W Trustee)
439 {
440 switch (Trustee->TrusteeForm)
441 {
442 case TRUSTEE_IS_NAME:
443 return Trustee->ptstrName;
444
445 case TRUSTEE_IS_OBJECTS_AND_NAME:
446 return ((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ptstrName;
447
448 default:
449 return NULL;
450 }
451 }
452
453 static DWORD
AccpLookupCurrentUser(OUT PSID * ppSid)454 AccpLookupCurrentUser(OUT PSID *ppSid)
455 {
456 DWORD Ret;
457 CHAR Buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
458 DWORD Length;
459 HANDLE Token;
460 PSID pSid;
461
462 *ppSid = NULL;
463 if (!OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &Token))
464 {
465 Ret = GetLastError();
466 if (Ret != ERROR_NO_TOKEN)
467 {
468 return Ret;
469 }
470
471 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &Token))
472 {
473 return GetLastError();
474 }
475 }
476
477 Length = sizeof(Buffer);
478 if (!GetTokenInformation(Token, TokenUser, Buffer, Length, &Length))
479 {
480 Ret = GetLastError();
481 CloseHandle(Token);
482 return Ret;
483 }
484 CloseHandle(Token);
485
486 pSid = ((PTOKEN_USER)Buffer)->User.Sid;
487 Length = GetLengthSid(pSid);
488 *ppSid = LocalAlloc(LMEM_FIXED, Length);
489 if (!*ppSid)
490 {
491 return ERROR_NOT_ENOUGH_MEMORY;
492 }
493 CopyMemory(*ppSid, pSid, Length);
494
495 return ERROR_SUCCESS;
496 }
497
498 static DWORD
AccpLookupSidByName(IN LSA_HANDLE PolicyHandle,IN LPWSTR Name,OUT PSID * pSid)499 AccpLookupSidByName(IN LSA_HANDLE PolicyHandle,
500 IN LPWSTR Name,
501 OUT PSID *pSid)
502 {
503 NTSTATUS Status;
504 LSA_UNICODE_STRING LsaNames[1];
505 PLSA_REFERENCED_DOMAIN_LIST ReferencedDomains = NULL;
506 PLSA_TRANSLATED_SID2 TranslatedSid = NULL;
507 DWORD SidLen;
508 SIZE_T NameLength;
509 DWORD Ret = ERROR_SUCCESS;
510
511 NameLength = wcslen(Name);
512 if (NameLength > UNICODE_STRING_MAX_CHARS)
513 {
514 return ERROR_INVALID_PARAMETER;
515 }
516
517 LsaNames[0].Buffer = Name;
518 LsaNames[0].Length = (USHORT)NameLength * sizeof(WCHAR);
519 LsaNames[0].MaximumLength = LsaNames[0].Length + sizeof(WCHAR);
520
521 Status = LsaLookupNames2(PolicyHandle,
522 0,
523 sizeof(LsaNames) / sizeof(LsaNames[0]),
524 LsaNames,
525 &ReferencedDomains,
526 &TranslatedSid);
527
528 if (!NT_SUCCESS(Status))
529 return LsaNtStatusToWinError(Status);
530
531 if (TranslatedSid->Use == SidTypeUnknown || TranslatedSid->Use == SidTypeInvalid)
532 {
533 Ret = LsaNtStatusToWinError(STATUS_NONE_MAPPED); /* FIXME- what error code? */
534 goto Cleanup;
535 }
536
537 SidLen = GetLengthSid(TranslatedSid->Sid);
538 ASSERT(SidLen != 0);
539
540 *pSid = LocalAlloc(LMEM_FIXED, (SIZE_T)SidLen);
541 if (*pSid != NULL)
542 {
543 if (!CopySid(SidLen,
544 *pSid,
545 TranslatedSid->Sid))
546 {
547 Ret = GetLastError();
548
549 LocalFree((HLOCAL)*pSid);
550 *pSid = NULL;
551 }
552 }
553 else
554 Ret = ERROR_NOT_ENOUGH_MEMORY;
555
556 Cleanup:
557 LsaFreeMemory(ReferencedDomains);
558 LsaFreeMemory(TranslatedSid);
559
560 return Ret;
561 }
562
563
564 static DWORD
AccpGetTrusteeSid(IN PTRUSTEE_W Trustee,IN OUT PLSA_HANDLE pPolicyHandle,OUT PSID * ppSid,OUT BOOL * Allocated)565 AccpGetTrusteeSid(IN PTRUSTEE_W Trustee,
566 IN OUT PLSA_HANDLE pPolicyHandle,
567 OUT PSID *ppSid,
568 OUT BOOL *Allocated)
569 {
570 DWORD Ret = ERROR_SUCCESS;
571 LPWSTR TrusteeName;
572
573 *ppSid = NULL;
574 *Allocated = FALSE;
575
576 /* Windows ignores this */
577 #if 0
578 if (Trustee->pMultipleTrustee || Trustee->MultipleTrusteeOperation != NO_MULTIPLE_TRUSTEE)
579 {
580 /* This is currently not supported */
581 return ERROR_INVALID_PARAMETER;
582 }
583 #endif
584
585 switch (Trustee->TrusteeForm)
586 {
587 case TRUSTEE_IS_OBJECTS_AND_NAME:
588 if (((POBJECTS_AND_NAME_W)Trustee->ptstrName)->ObjectsPresent != 0)
589 {
590 /* This is not supported as there is no way to interpret the
591 strings provided, and we need GUIDs for the ACEs... */
592 Ret = ERROR_INVALID_PARAMETER;
593 break;
594 }
595 /* fall through */
596
597 case TRUSTEE_IS_NAME:
598 TrusteeName = AccpGetTrusteeName(Trustee);
599 if (!wcscmp(TrusteeName, L"CURRENT_USER"))
600 {
601 Ret = AccpLookupCurrentUser(ppSid);
602 if (Ret == ERROR_SUCCESS)
603 {
604 ASSERT(*ppSid != NULL);
605 *Allocated = TRUE;
606 }
607 break;
608 }
609
610 if (*pPolicyHandle == NULL)
611 {
612 Ret = AccpOpenLSAPolicyHandle(NULL, /* FIXME - always local? */
613 POLICY_LOOKUP_NAMES,
614 pPolicyHandle);
615 if (Ret != ERROR_SUCCESS)
616 return Ret;
617
618 ASSERT(*pPolicyHandle != NULL);
619 }
620
621 Ret = AccpLookupSidByName(*pPolicyHandle,
622 TrusteeName,
623 ppSid);
624 if (Ret == ERROR_SUCCESS)
625 {
626 ASSERT(*ppSid != NULL);
627 *Allocated = TRUE;
628 }
629 break;
630
631 case TRUSTEE_IS_OBJECTS_AND_SID:
632 *ppSid = ((POBJECTS_AND_SID)Trustee->ptstrName)->pSid;
633 break;
634
635 case TRUSTEE_IS_SID:
636 *ppSid = (PSID)Trustee->ptstrName;
637 break;
638
639 default:
640 Ret = ERROR_INVALID_PARAMETER;
641 break;
642 }
643
644 return Ret;
645 }
646
647
648 /**********************************************************************
649 * AccRewriteGetHandleRights EXPORTED
650 *
651 * @unimplemented
652 */
653 DWORD WINAPI
AccRewriteGetHandleRights(HANDLE handle,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID * ppsidOwner,PSID * ppsidGroup,PACL * ppDacl,PACL * ppSacl,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)654 AccRewriteGetHandleRights(HANDLE handle,
655 SE_OBJECT_TYPE ObjectType,
656 SECURITY_INFORMATION SecurityInfo,
657 PSID* ppsidOwner,
658 PSID* ppsidGroup,
659 PACL* ppDacl,
660 PACL* ppSacl,
661 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
662 {
663 PSECURITY_DESCRIPTOR pSD = NULL;
664 ULONG SDSize = 0;
665 NTSTATUS Status;
666 DWORD LastErr;
667 DWORD Ret;
668
669 /* save the last error code */
670 LastErr = GetLastError();
671
672 do
673 {
674 Ret = ERROR_SUCCESS;
675
676 /* allocate a buffer large enough to hold the
677 security descriptor we need to return */
678 SDSize += 0x100;
679 if (pSD == NULL)
680 {
681 pSD = LocalAlloc(LMEM_FIXED,
682 (SIZE_T)SDSize);
683 }
684 else
685 {
686 PSECURITY_DESCRIPTOR newSD;
687
688 newSD = LocalReAlloc((HLOCAL)pSD,
689 (SIZE_T)SDSize,
690 LMEM_MOVEABLE);
691 if (newSD != NULL)
692 pSD = newSD;
693 }
694
695 if (pSD == NULL)
696 {
697 Ret = GetLastError();
698 break;
699 }
700
701 /* perform the actual query depending on the object type */
702 switch (ObjectType)
703 {
704 case SE_REGISTRY_KEY:
705 {
706 Ret = (DWORD)RegGetKeySecurity((HKEY)handle,
707 SecurityInfo,
708 pSD,
709 &SDSize);
710 break;
711 }
712
713 case SE_FILE_OBJECT:
714 /* FIXME - handle console handles? */
715 case SE_KERNEL_OBJECT:
716 {
717 Status = NtQuerySecurityObject(handle,
718 SecurityInfo,
719 pSD,
720 SDSize,
721 &SDSize);
722 if (!NT_SUCCESS(Status))
723 {
724 Ret = RtlNtStatusToDosError(Status);
725 }
726 break;
727 }
728
729 case SE_SERVICE:
730 {
731 if (!QueryServiceObjectSecurity((SC_HANDLE)handle,
732 SecurityInfo,
733 pSD,
734 SDSize,
735 &SDSize))
736 {
737 Ret = GetLastError();
738 }
739 break;
740 }
741
742 case SE_WINDOW_OBJECT:
743 {
744 if (!GetUserObjectSecurity(handle,
745 &SecurityInfo,
746 pSD,
747 SDSize,
748 &SDSize))
749 {
750 Ret = GetLastError();
751 }
752 break;
753 }
754
755 default:
756 {
757 UNIMPLEMENTED;
758 Ret = ERROR_CALL_NOT_IMPLEMENTED;
759 break;
760 }
761 }
762
763 } while (Ret == ERROR_INSUFFICIENT_BUFFER);
764
765 if (Ret == ERROR_SUCCESS)
766 {
767 BOOL Present, Defaulted;
768
769 if (SecurityInfo & OWNER_SECURITY_INFORMATION && ppsidOwner != NULL)
770 {
771 *ppsidOwner = NULL;
772 if (!GetSecurityDescriptorOwner(pSD,
773 ppsidOwner,
774 &Defaulted))
775 {
776 Ret = GetLastError();
777 goto Cleanup;
778 }
779 }
780
781 if (SecurityInfo & GROUP_SECURITY_INFORMATION && ppsidGroup != NULL)
782 {
783 *ppsidGroup = NULL;
784 if (!GetSecurityDescriptorGroup(pSD,
785 ppsidGroup,
786 &Defaulted))
787 {
788 Ret = GetLastError();
789 goto Cleanup;
790 }
791 }
792
793 if (SecurityInfo & DACL_SECURITY_INFORMATION && ppDacl != NULL)
794 {
795 *ppDacl = NULL;
796 if (!GetSecurityDescriptorDacl(pSD,
797 &Present,
798 ppDacl,
799 &Defaulted))
800 {
801 Ret = GetLastError();
802 goto Cleanup;
803 }
804 }
805
806 if (SecurityInfo & SACL_SECURITY_INFORMATION && ppSacl != NULL)
807 {
808 *ppSacl = NULL;
809 if (!GetSecurityDescriptorSacl(pSD,
810 &Present,
811 ppSacl,
812 &Defaulted))
813 {
814 Ret = GetLastError();
815 goto Cleanup;
816 }
817 }
818
819 *ppSecurityDescriptor = pSD;
820 }
821 else
822 {
823 Cleanup:
824 if (pSD != NULL)
825 {
826 LocalFree((HLOCAL)pSD);
827 }
828 }
829
830 /* restore the last error code */
831 SetLastError(LastErr);
832
833 return Ret;
834 }
835
836
837 /**********************************************************************
838 * AccRewriteSetHandleRights EXPORTED
839 *
840 * @unimplemented
841 */
842 DWORD WINAPI
AccRewriteSetHandleRights(HANDLE handle,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSECURITY_DESCRIPTOR pSecurityDescriptor)843 AccRewriteSetHandleRights(HANDLE handle,
844 SE_OBJECT_TYPE ObjectType,
845 SECURITY_INFORMATION SecurityInfo,
846 PSECURITY_DESCRIPTOR pSecurityDescriptor)
847 {
848 NTSTATUS Status;
849 DWORD LastErr;
850 DWORD Ret = ERROR_SUCCESS;
851
852 /* save the last error code */
853 LastErr = GetLastError();
854
855 /* set the security according to the object type */
856 switch (ObjectType)
857 {
858 case SE_REGISTRY_KEY:
859 {
860 Ret = (DWORD)RegSetKeySecurity((HKEY)handle,
861 SecurityInfo,
862 pSecurityDescriptor);
863 break;
864 }
865
866 case SE_FILE_OBJECT:
867 /* FIXME - handle console handles? */
868 case SE_KERNEL_OBJECT:
869 {
870 Status = NtSetSecurityObject(handle,
871 SecurityInfo,
872 pSecurityDescriptor);
873 if (!NT_SUCCESS(Status))
874 {
875 Ret = RtlNtStatusToDosError(Status);
876 }
877 break;
878 }
879
880 case SE_SERVICE:
881 {
882 if (!SetServiceObjectSecurity((SC_HANDLE)handle,
883 SecurityInfo,
884 pSecurityDescriptor))
885 {
886 Ret = GetLastError();
887 }
888 break;
889 }
890
891 case SE_WINDOW_OBJECT:
892 {
893 if (!SetUserObjectSecurity(handle,
894 &SecurityInfo,
895 pSecurityDescriptor))
896 {
897 Ret = GetLastError();
898 }
899 break;
900 }
901
902 default:
903 {
904 UNIMPLEMENTED;
905 Ret = ERROR_CALL_NOT_IMPLEMENTED;
906 break;
907 }
908 }
909
910
911 /* restore the last error code */
912 SetLastError(LastErr);
913
914 return Ret;
915 }
916
917
918 static DWORD
AccpOpenNamedObject(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PHANDLE Handle,PHANDLE Handle2,BOOL Write)919 AccpOpenNamedObject(LPWSTR pObjectName,
920 SE_OBJECT_TYPE ObjectType,
921 SECURITY_INFORMATION SecurityInfo,
922 PHANDLE Handle,
923 PHANDLE Handle2,
924 BOOL Write)
925 {
926 LPWSTR lpPath;
927 NTSTATUS Status;
928 ACCESS_MASK DesiredAccess = (ACCESS_MASK)0;
929 DWORD Ret = ERROR_SUCCESS;
930
931 /* determine the required access rights */
932 switch (ObjectType)
933 {
934 case SE_REGISTRY_KEY:
935 case SE_FILE_OBJECT:
936 case SE_KERNEL_OBJECT:
937 case SE_SERVICE:
938 case SE_WINDOW_OBJECT:
939 if (Write)
940 {
941 SetSecurityAccessMask(SecurityInfo,
942 (PDWORD)&DesiredAccess);
943 }
944 else
945 {
946 QuerySecurityAccessMask(SecurityInfo,
947 (PDWORD)&DesiredAccess);
948 }
949 break;
950
951 default:
952 break;
953 }
954
955 /* make a copy of the path if we're modifying the string */
956 switch (ObjectType)
957 {
958 case SE_REGISTRY_KEY:
959 case SE_SERVICE:
960 lpPath = (LPWSTR)LocalAlloc(LMEM_FIXED,
961 (wcslen(pObjectName) + 1) * sizeof(WCHAR));
962 if (lpPath == NULL)
963 {
964 Ret = GetLastError();
965 goto Cleanup;
966 }
967
968 wcscpy(lpPath,
969 pObjectName);
970 break;
971
972 default:
973 lpPath = pObjectName;
974 break;
975 }
976
977 /* open a handle to the path depending on the object type */
978 switch (ObjectType)
979 {
980 case SE_FILE_OBJECT:
981 {
982 IO_STATUS_BLOCK IoStatusBlock;
983 OBJECT_ATTRIBUTES ObjectAttributes;
984 UNICODE_STRING FileName;
985
986 if (!RtlDosPathNameToNtPathName_U(pObjectName,
987 &FileName,
988 NULL,
989 NULL))
990 {
991 Ret = ERROR_INVALID_NAME;
992 goto Cleanup;
993 }
994
995 InitializeObjectAttributes(&ObjectAttributes,
996 &FileName,
997 OBJ_CASE_INSENSITIVE,
998 NULL,
999 NULL);
1000
1001 Status = NtOpenFile(Handle,
1002 DesiredAccess | SYNCHRONIZE,
1003 &ObjectAttributes,
1004 &IoStatusBlock,
1005 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1006 FILE_SYNCHRONOUS_IO_NONALERT);
1007
1008 RtlFreeHeap(RtlGetProcessHeap(),
1009 0,
1010 FileName.Buffer);
1011
1012 if (!NT_SUCCESS(Status))
1013 {
1014 Ret = RtlNtStatusToDosError(Status);
1015 }
1016 break;
1017 }
1018
1019 case SE_REGISTRY_KEY:
1020 {
1021 static const struct
1022 {
1023 HKEY hRootKey;
1024 LPCWSTR szRootKey;
1025 } AccRegRootKeys[] =
1026 {
1027 {HKEY_CLASSES_ROOT, L"CLASSES_ROOT"},
1028 {HKEY_CURRENT_USER, L"CURRENT_USER"},
1029 {HKEY_LOCAL_MACHINE, L"MACHINE"},
1030 {HKEY_USERS, L"USERS"},
1031 {HKEY_CURRENT_CONFIG, L"CONFIG"},
1032 };
1033 LPWSTR lpMachineName, lpRootKeyName, lpKeyName;
1034 HKEY hRootKey = NULL;
1035 UINT i;
1036
1037 /* parse the registry path */
1038 if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
1039 {
1040 lpMachineName = lpPath;
1041
1042 lpRootKeyName = wcschr(lpPath + 2,
1043 L'\\');
1044 if (lpRootKeyName == NULL)
1045 goto ParseRegErr;
1046 else
1047 *(lpRootKeyName++) = L'\0';
1048 }
1049 else
1050 {
1051 lpMachineName = NULL;
1052 lpRootKeyName = lpPath;
1053 }
1054
1055 lpKeyName = wcschr(lpRootKeyName,
1056 L'\\');
1057 if (lpKeyName != NULL)
1058 {
1059 *(lpKeyName++) = L'\0';
1060 }
1061
1062 for (i = 0;
1063 i != sizeof(AccRegRootKeys) / sizeof(AccRegRootKeys[0]);
1064 i++)
1065 {
1066 if (!_wcsicmp(lpRootKeyName,
1067 AccRegRootKeys[i].szRootKey))
1068 {
1069 hRootKey = AccRegRootKeys[i].hRootKey;
1070 break;
1071 }
1072 }
1073
1074 if (hRootKey == NULL)
1075 {
1076 ParseRegErr:
1077 /* FIXME - right error code? */
1078 Ret = ERROR_INVALID_PARAMETER;
1079 goto Cleanup;
1080 }
1081
1082 /* open the registry key */
1083 if (lpMachineName != NULL)
1084 {
1085 Ret = RegConnectRegistry(lpMachineName,
1086 hRootKey,
1087 (PHKEY)Handle2);
1088
1089 if (Ret != ERROR_SUCCESS)
1090 goto Cleanup;
1091
1092 hRootKey = (HKEY)(*Handle2);
1093 }
1094
1095 Ret = RegOpenKeyEx(hRootKey,
1096 lpKeyName,
1097 0,
1098 (REGSAM)DesiredAccess,
1099 (PHKEY)Handle);
1100 if (Ret != ERROR_SUCCESS)
1101 {
1102 if (*Handle2 != NULL)
1103 {
1104 RegCloseKey((HKEY)(*Handle2));
1105 }
1106
1107 goto Cleanup;
1108 }
1109 break;
1110 }
1111
1112 case SE_SERVICE:
1113 {
1114 LPWSTR lpServiceName, lpMachineName;
1115
1116 /* parse the service path */
1117 if (lpPath[0] == L'\\' && lpPath[1] == L'\\')
1118 {
1119 DesiredAccess |= SC_MANAGER_CONNECT;
1120
1121 lpMachineName = lpPath;
1122
1123 lpServiceName = wcschr(lpPath + 2,
1124 L'\\');
1125 if (lpServiceName == NULL)
1126 {
1127 /* FIXME - right error code? */
1128 Ret = ERROR_INVALID_PARAMETER;
1129 goto Cleanup;
1130 }
1131 else
1132 *(lpServiceName++) = L'\0';
1133 }
1134 else
1135 {
1136 lpMachineName = NULL;
1137 lpServiceName = lpPath;
1138 }
1139
1140 /* open the service */
1141 *Handle2 = (HANDLE)OpenSCManager(lpMachineName,
1142 NULL,
1143 (DWORD)DesiredAccess);
1144 if (*Handle2 == NULL)
1145 {
1146 Ret = GetLastError();
1147 ASSERT(Ret != ERROR_SUCCESS);
1148 goto Cleanup;
1149 }
1150
1151 DesiredAccess &= ~SC_MANAGER_CONNECT;
1152 *Handle = (HANDLE)OpenService((SC_HANDLE)(*Handle2),
1153 lpServiceName,
1154 (DWORD)DesiredAccess);
1155 if (*Handle == NULL)
1156 {
1157 Ret = GetLastError();
1158 ASSERT(Ret != ERROR_SUCCESS);
1159 ASSERT(*Handle2 != NULL);
1160 CloseServiceHandle((SC_HANDLE)(*Handle2));
1161
1162 goto Cleanup;
1163 }
1164 break;
1165 }
1166
1167 default:
1168 {
1169 UNIMPLEMENTED;
1170 Ret = ERROR_CALL_NOT_IMPLEMENTED;
1171 break;
1172 }
1173 }
1174
1175 Cleanup:
1176 if (lpPath != NULL && lpPath != pObjectName)
1177 {
1178 LocalFree((HLOCAL)lpPath);
1179 }
1180
1181 return Ret;
1182 }
1183
1184
1185 static VOID
AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,HANDLE Handle,HANDLE Handle2)1186 AccpCloseObjectHandle(SE_OBJECT_TYPE ObjectType,
1187 HANDLE Handle,
1188 HANDLE Handle2)
1189 {
1190 ASSERT(Handle != NULL);
1191
1192 /* close allocated handles depending on the object type */
1193 switch (ObjectType)
1194 {
1195 case SE_REGISTRY_KEY:
1196 RegCloseKey((HKEY)Handle);
1197 if (Handle2 != NULL)
1198 RegCloseKey((HKEY)Handle2);
1199 break;
1200
1201 case SE_FILE_OBJECT:
1202 NtClose(Handle);
1203 break;
1204
1205 case SE_KERNEL_OBJECT:
1206 case SE_WINDOW_OBJECT:
1207 CloseHandle(Handle);
1208 break;
1209
1210 case SE_SERVICE:
1211 CloseServiceHandle((SC_HANDLE)Handle);
1212 ASSERT(Handle2 != NULL);
1213 CloseServiceHandle((SC_HANDLE)Handle2);
1214 break;
1215
1216 default:
1217 break;
1218 }
1219 }
1220
1221
1222 /**********************************************************************
1223 * AccRewriteGetNamedRights EXPORTED
1224 *
1225 * @unimplemented
1226 */
1227 DWORD WINAPI
AccRewriteGetNamedRights(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID * ppsidOwner,PSID * ppsidGroup,PACL * ppDacl,PACL * ppSacl,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)1228 AccRewriteGetNamedRights(LPWSTR pObjectName,
1229 SE_OBJECT_TYPE ObjectType,
1230 SECURITY_INFORMATION SecurityInfo,
1231 PSID* ppsidOwner,
1232 PSID* ppsidGroup,
1233 PACL* ppDacl,
1234 PACL* ppSacl,
1235 PSECURITY_DESCRIPTOR* ppSecurityDescriptor)
1236 {
1237 HANDLE Handle = NULL;
1238 HANDLE Handle2 = NULL;
1239 DWORD LastErr;
1240 DWORD Ret;
1241
1242 /* save the last error code */
1243 LastErr = GetLastError();
1244
1245 /* create the handle */
1246 Ret = AccpOpenNamedObject(pObjectName,
1247 ObjectType,
1248 SecurityInfo,
1249 &Handle,
1250 &Handle2,
1251 FALSE);
1252
1253 if (Ret == ERROR_SUCCESS)
1254 {
1255 ASSERT(Handle != NULL);
1256
1257 /* perform the operation */
1258 Ret = AccRewriteGetHandleRights(Handle,
1259 ObjectType,
1260 SecurityInfo,
1261 ppsidOwner,
1262 ppsidGroup,
1263 ppDacl,
1264 ppSacl,
1265 ppSecurityDescriptor);
1266
1267 /* close opened handles */
1268 AccpCloseObjectHandle(ObjectType,
1269 Handle,
1270 Handle2);
1271 }
1272
1273 /* restore the last error code */
1274 SetLastError(LastErr);
1275
1276 return Ret;
1277 }
1278
1279
1280 /**********************************************************************
1281 * AccRewriteSetNamedRights EXPORTED
1282 *
1283 * @unimplemented
1284 */
1285 DWORD WINAPI
AccRewriteSetNamedRights(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSECURITY_DESCRIPTOR pSecurityDescriptor)1286 AccRewriteSetNamedRights(LPWSTR pObjectName,
1287 SE_OBJECT_TYPE ObjectType,
1288 SECURITY_INFORMATION SecurityInfo,
1289 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1290 {
1291 HANDLE Handle = NULL;
1292 HANDLE Handle2 = NULL;
1293 DWORD LastErr;
1294 DWORD Ret;
1295
1296 /* save the last error code */
1297 LastErr = GetLastError();
1298
1299 /* create the handle */
1300 Ret = AccpOpenNamedObject(pObjectName,
1301 ObjectType,
1302 SecurityInfo,
1303 &Handle,
1304 &Handle2,
1305 TRUE);
1306
1307 if (Ret == ERROR_SUCCESS)
1308 {
1309 ASSERT(Handle != NULL);
1310
1311 /* perform the operation */
1312 Ret = AccRewriteSetHandleRights(Handle,
1313 ObjectType,
1314 SecurityInfo,
1315 pSecurityDescriptor);
1316
1317 /* close opened handles */
1318 AccpCloseObjectHandle(ObjectType,
1319 Handle,
1320 Handle2);
1321 }
1322
1323 /* restore the last error code */
1324 SetLastError(LastErr);
1325
1326 return Ret;
1327 }
1328
1329
1330 /**********************************************************************
1331 * AccRewriteSetEntriesInAcl EXPORTED
1332 *
1333 * @implemented
1334 */
1335 DWORD WINAPI
AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,PEXPLICIT_ACCESS_W pListOfExplicitEntries,PACL OldAcl,PACL * NewAcl)1336 AccRewriteSetEntriesInAcl(ULONG cCountOfExplicitEntries,
1337 PEXPLICIT_ACCESS_W pListOfExplicitEntries,
1338 PACL OldAcl,
1339 PACL* NewAcl)
1340 {
1341 PACL pNew = NULL;
1342 ACL_SIZE_INFORMATION SizeInformation;
1343 PACE_HEADER pAce;
1344 BOOLEAN KeepAceBuf[8];
1345 BOOLEAN *pKeepAce = NULL;
1346 GUID ObjectTypeGuid, InheritedObjectTypeGuid;
1347 DWORD ObjectsPresent;
1348 BOOL needToClean;
1349 PSID pSid1, pSid2;
1350 ULONG i, j;
1351 LSA_HANDLE PolicyHandle = NULL;
1352 BOOL bRet;
1353 DWORD LastErr;
1354 DWORD Ret = ERROR_SUCCESS;
1355
1356 /* save the last error code */
1357 LastErr = GetLastError();
1358
1359 *NewAcl = NULL;
1360
1361 /* Get information about previous ACL */
1362 if (OldAcl)
1363 {
1364 if (!GetAclInformation(OldAcl, &SizeInformation, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation))
1365 {
1366 Ret = GetLastError();
1367 goto Cleanup;
1368 }
1369
1370 if (SizeInformation.AceCount > sizeof(KeepAceBuf) / sizeof(KeepAceBuf[0]))
1371 {
1372 pKeepAce = (BOOLEAN *)LocalAlloc(LMEM_FIXED, SizeInformation.AceCount * sizeof(*pKeepAce));
1373 if (!pKeepAce)
1374 {
1375 Ret = ERROR_NOT_ENOUGH_MEMORY;
1376 goto Cleanup;
1377 }
1378 }
1379 else
1380 pKeepAce = KeepAceBuf;
1381
1382 memset(pKeepAce, TRUE, SizeInformation.AceCount * sizeof(*pKeepAce));
1383 }
1384 else
1385 {
1386 ZeroMemory(&SizeInformation, sizeof(ACL_SIZE_INFORMATION));
1387 SizeInformation.AclBytesInUse = sizeof(ACL);
1388 }
1389
1390 /* Get size required for new entries */
1391 for (i = 0; i < cCountOfExplicitEntries; i++)
1392 {
1393 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1394 &PolicyHandle,
1395 &pSid1,
1396 &needToClean);
1397 if (Ret != ERROR_SUCCESS)
1398 goto Cleanup;
1399
1400 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1401 NULL,
1402 NULL);
1403
1404 switch (pListOfExplicitEntries[i].grfAccessMode)
1405 {
1406 case REVOKE_ACCESS:
1407 case SET_ACCESS:
1408 /* Discard all accesses for the trustee... */
1409 for (j = 0; j < SizeInformation.AceCount; j++)
1410 {
1411 if (!pKeepAce[j])
1412 continue;
1413 if (!GetAce(OldAcl, j, (PVOID*)&pAce))
1414 {
1415 Ret = GetLastError();
1416 goto Cleanup;
1417 }
1418
1419 pSid2 = AccpGetAceSid(pAce);
1420 if (RtlEqualSid(pSid1, pSid2))
1421 {
1422 pKeepAce[j] = FALSE;
1423 SizeInformation.AclBytesInUse -= pAce->AceSize;
1424 }
1425 }
1426 if (pListOfExplicitEntries[i].grfAccessMode == REVOKE_ACCESS)
1427 break;
1428 /* ...and replace by the current access */
1429 case GRANT_ACCESS:
1430 case DENY_ACCESS:
1431 /* Add to ACL */
1432 SizeInformation.AclBytesInUse += AccpCalcNeededAceSize(pSid1, ObjectsPresent);
1433 break;
1434 case SET_AUDIT_SUCCESS:
1435 case SET_AUDIT_FAILURE:
1436 /* FIXME */
1437 DPRINT1("Case not implemented!\n");
1438 break;
1439 default:
1440 DPRINT1("Unknown access mode 0x%x. Ignoring it\n", pListOfExplicitEntries[i].grfAccessMode);
1441 break;
1442 }
1443
1444 if (needToClean)
1445 LocalFree((HLOCAL)pSid1);
1446 }
1447
1448 /* Succeed, if no ACL needs to be allocated */
1449 if (SizeInformation.AclBytesInUse == 0)
1450 goto Cleanup;
1451
1452 /* OK, now create the new ACL */
1453 DPRINT("Allocating %u bytes for the new ACL\n", SizeInformation.AclBytesInUse);
1454 pNew = (PACL)LocalAlloc(LMEM_FIXED, SizeInformation.AclBytesInUse);
1455 if (!pNew)
1456 {
1457 Ret = ERROR_NOT_ENOUGH_MEMORY;
1458 goto Cleanup;
1459 }
1460 if (!InitializeAcl(pNew, SizeInformation.AclBytesInUse, ACL_REVISION))
1461 {
1462 Ret = GetLastError();
1463 goto Cleanup;
1464 }
1465
1466 /* Fill it */
1467 /* 1a) New audit entries (SET_AUDIT_SUCCESS, SET_AUDIT_FAILURE) */
1468 /* FIXME */
1469
1470 /* 1b) Existing audit entries */
1471 /* FIXME */
1472
1473 /* 2a) New denied entries (DENY_ACCESS) */
1474 for (i = 0; i < cCountOfExplicitEntries; i++)
1475 {
1476 if (pListOfExplicitEntries[i].grfAccessMode == DENY_ACCESS)
1477 {
1478 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1479 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1480 &PolicyHandle,
1481 &pSid1,
1482 &needToClean);
1483 if (Ret != ERROR_SUCCESS)
1484 goto Cleanup;
1485
1486 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1487 &ObjectTypeGuid,
1488 &InheritedObjectTypeGuid);
1489
1490 if (ObjectsPresent == 0)
1491 {
1492 /* FIXME: Call AddAccessDeniedAceEx instead! */
1493 bRet = AddAccessDeniedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1494 }
1495 else
1496 {
1497 /* FIXME: Call AddAccessDeniedObjectAce */
1498 DPRINT1("Object ACEs not yet supported!\n");
1499 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1500 bRet = FALSE;
1501 }
1502
1503 if (needToClean) LocalFree((HLOCAL)pSid1);
1504 if (!bRet)
1505 {
1506 Ret = GetLastError();
1507 goto Cleanup;
1508 }
1509 }
1510 }
1511
1512 /* 2b) Existing denied entries */
1513 /* FIXME */
1514
1515 /* 3a) New allow entries (GRANT_ACCESS, SET_ACCESS) */
1516 for (i = 0; i < cCountOfExplicitEntries; i++)
1517 {
1518 if (pListOfExplicitEntries[i].grfAccessMode == SET_ACCESS ||
1519 pListOfExplicitEntries[i].grfAccessMode == GRANT_ACCESS)
1520 {
1521 /* FIXME: take care of pListOfExplicitEntries[i].grfInheritance */
1522 Ret = AccpGetTrusteeSid(&pListOfExplicitEntries[i].Trustee,
1523 &PolicyHandle,
1524 &pSid1,
1525 &needToClean);
1526 if (Ret != ERROR_SUCCESS)
1527 goto Cleanup;
1528
1529 ObjectsPresent = AccpGetTrusteeObjects(&pListOfExplicitEntries[i].Trustee,
1530 &ObjectTypeGuid,
1531 &InheritedObjectTypeGuid);
1532
1533 if (ObjectsPresent == 0)
1534 {
1535 /* FIXME: Call AddAccessAllowedAceEx instead! */
1536 bRet = AddAccessAllowedAce(pNew, ACL_REVISION, pListOfExplicitEntries[i].grfAccessPermissions, pSid1);
1537 }
1538 else
1539 {
1540 /* FIXME: Call AddAccessAllowedObjectAce */
1541 DPRINT1("Object ACEs not yet supported!\n");
1542 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1543 bRet = FALSE;
1544 }
1545
1546 if (needToClean) LocalFree((HLOCAL)pSid1);
1547 if (!bRet)
1548 {
1549 Ret = GetLastError();
1550 goto Cleanup;
1551 }
1552 }
1553 }
1554
1555 /* 3b) Existing allow entries */
1556 /* FIXME */
1557
1558 *NewAcl = pNew;
1559
1560 Cleanup:
1561 if (pKeepAce && pKeepAce != KeepAceBuf)
1562 LocalFree((HLOCAL)pKeepAce);
1563
1564 if (pNew && Ret != ERROR_SUCCESS)
1565 LocalFree((HLOCAL)pNew);
1566
1567 if (PolicyHandle)
1568 LsaClose(PolicyHandle);
1569
1570 /* restore the last error code */
1571 SetLastError(LastErr);
1572
1573 return Ret;
1574 }
1575
1576
1577 /**********************************************************************
1578 * AccGetInheritanceSource EXPORTED
1579 *
1580 * @unimplemented
1581 */
1582 DWORD WINAPI
AccGetInheritanceSource(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,BOOL Container,GUID ** pObjectClassGuids,DWORD GuidCount,PACL pAcl,PFN_OBJECT_MGR_FUNCTS pfnArray,PGENERIC_MAPPING pGenericMapping,PINHERITED_FROMW pInheritArray)1583 AccGetInheritanceSource(LPWSTR pObjectName,
1584 SE_OBJECT_TYPE ObjectType,
1585 SECURITY_INFORMATION SecurityInfo,
1586 BOOL Container,
1587 GUID** pObjectClassGuids,
1588 DWORD GuidCount,
1589 PACL pAcl,
1590 PFN_OBJECT_MGR_FUNCTS pfnArray,
1591 PGENERIC_MAPPING pGenericMapping,
1592 PINHERITED_FROMW pInheritArray)
1593 {
1594 UNIMPLEMENTED;
1595 return ERROR_CALL_NOT_IMPLEMENTED;
1596 }
1597
1598
1599 /**********************************************************************
1600 * AccFreeIndexArray EXPORTED
1601 *
1602 * @implemented
1603 */
1604 DWORD WINAPI
AccFreeIndexArray(PINHERITED_FROMW pInheritArray,USHORT AceCnt,PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)1605 AccFreeIndexArray(PINHERITED_FROMW pInheritArray,
1606 USHORT AceCnt,
1607 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
1608 {
1609 PINHERITED_FROMW pLast;
1610
1611 UNREFERENCED_PARAMETER(pfnArray);
1612
1613 pLast = pInheritArray + AceCnt;
1614 while (pInheritArray != pLast)
1615 {
1616 if (pInheritArray->AncestorName != NULL)
1617 {
1618 LocalFree((HLOCAL)pInheritArray->AncestorName);
1619 pInheritArray->AncestorName = NULL;
1620 }
1621
1622 pInheritArray++;
1623 }
1624
1625 return ERROR_SUCCESS;
1626 }
1627
1628
1629 /**********************************************************************
1630 * AccRewriteGetExplicitEntriesFromAcl EXPORTED
1631 *
1632 * @implemented
1633 */
1634 DWORD WINAPI
AccRewriteGetExplicitEntriesFromAcl(PACL pacl,PULONG pcCountOfExplicitEntries,PEXPLICIT_ACCESS_W * pListOfExplicitEntries)1635 AccRewriteGetExplicitEntriesFromAcl(PACL pacl,
1636 PULONG pcCountOfExplicitEntries,
1637 PEXPLICIT_ACCESS_W* pListOfExplicitEntries)
1638 {
1639 PACE_HEADER AceHeader;
1640 PSID Sid, SidTarget;
1641 ULONG ObjectAceCount = 0;
1642 POBJECTS_AND_SID ObjSid;
1643 SIZE_T Size;
1644 PEXPLICIT_ACCESS_W peaw;
1645 DWORD LastErr, SidLen;
1646 DWORD AceIndex = 0;
1647 DWORD ErrorCode = ERROR_SUCCESS;
1648
1649 /* save the last error code */
1650 LastErr = GetLastError();
1651
1652 if (pacl != NULL)
1653 {
1654 if (pacl->AceCount != 0)
1655 {
1656 Size = (SIZE_T)pacl->AceCount * sizeof(EXPLICIT_ACCESS_W);
1657
1658 /* calculate the space needed */
1659 while (GetAce(pacl,
1660 AceIndex,
1661 (LPVOID*)&AceHeader))
1662 {
1663 Sid = AccpGetAceSid(AceHeader);
1664 Size += GetLengthSid(Sid);
1665
1666 if (AccpIsObjectAce(AceHeader))
1667 ObjectAceCount++;
1668
1669 AceIndex++;
1670 }
1671
1672 Size += ObjectAceCount * sizeof(OBJECTS_AND_SID);
1673
1674 ASSERT(pacl->AceCount == AceIndex);
1675
1676 /* allocate the array */
1677 peaw = (PEXPLICIT_ACCESS_W)LocalAlloc(LMEM_FIXED,
1678 Size);
1679 if (peaw != NULL)
1680 {
1681 AceIndex = 0;
1682 ObjSid = (POBJECTS_AND_SID)(peaw + pacl->AceCount);
1683 SidTarget = (PSID)(ObjSid + ObjectAceCount);
1684
1685 /* initialize the array */
1686 while (GetAce(pacl,
1687 AceIndex,
1688 (LPVOID*)&AceHeader))
1689 {
1690 Sid = AccpGetAceSid(AceHeader);
1691 SidLen = GetLengthSid(Sid);
1692
1693 peaw[AceIndex].grfAccessPermissions = AccpGetAceAccessMask(AceHeader);
1694 peaw[AceIndex].grfAccessMode = AccpGetAceAccessMode(AceHeader);
1695 peaw[AceIndex].grfInheritance = AceHeader->AceFlags & VALID_INHERIT_FLAGS;
1696
1697 if (CopySid(SidLen,
1698 SidTarget,
1699 Sid))
1700 {
1701 if (AccpIsObjectAce(AceHeader))
1702 {
1703 BuildTrusteeWithObjectsAndSid(&peaw[AceIndex].Trustee,
1704 ObjSid++,
1705 AccpGetObjectAceObjectType(AceHeader),
1706 AccpGetObjectAceInheritedObjectType(AceHeader),
1707 SidTarget);
1708 }
1709 else
1710 {
1711 BuildTrusteeWithSid(&peaw[AceIndex].Trustee,
1712 SidTarget);
1713 }
1714
1715 SidTarget = (PSID)((ULONG_PTR)SidTarget + SidLen);
1716 }
1717 else
1718 {
1719 /* copying the SID failed, treat it as an fatal error... */
1720 ErrorCode = GetLastError();
1721
1722 /* free allocated resources */
1723 LocalFree(peaw);
1724 peaw = NULL;
1725 AceIndex = 0;
1726 break;
1727 }
1728
1729 AceIndex++;
1730 }
1731
1732 *pcCountOfExplicitEntries = AceIndex;
1733 *pListOfExplicitEntries = peaw;
1734 }
1735 else
1736 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1737 }
1738 else
1739 {
1740 goto EmptyACL;
1741 }
1742 }
1743 else
1744 {
1745 EmptyACL:
1746 *pcCountOfExplicitEntries = 0;
1747 *pListOfExplicitEntries = NULL;
1748 }
1749
1750 /* restore the last error code */
1751 SetLastError(LastErr);
1752
1753 return ErrorCode;
1754 }
1755
1756
1757 /**********************************************************************
1758 * AccTreeResetNamedSecurityInfo EXPORTED
1759 *
1760 * @unimplemented
1761 */
1762 DWORD WINAPI
AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,SE_OBJECT_TYPE ObjectType,SECURITY_INFORMATION SecurityInfo,PSID pOwner,PSID pGroup,PACL pDacl,PACL pSacl,BOOL KeepExplicit,FN_PROGRESSW fnProgress,PROG_INVOKE_SETTING ProgressInvokeSetting,PVOID Args)1763 AccTreeResetNamedSecurityInfo(LPWSTR pObjectName,
1764 SE_OBJECT_TYPE ObjectType,
1765 SECURITY_INFORMATION SecurityInfo,
1766 PSID pOwner,
1767 PSID pGroup,
1768 PACL pDacl,
1769 PACL pSacl,
1770 BOOL KeepExplicit,
1771 FN_PROGRESSW fnProgress,
1772 PROG_INVOKE_SETTING ProgressInvokeSetting,
1773 PVOID Args)
1774 {
1775 UNIMPLEMENTED;
1776 return ERROR_CALL_NOT_IMPLEMENTED;
1777 }
1778
1779
1780 BOOL WINAPI
DllMain(IN HINSTANCE hinstDLL,IN DWORD dwReason,IN LPVOID lpvReserved)1781 DllMain(IN HINSTANCE hinstDLL,
1782 IN DWORD dwReason,
1783 IN LPVOID lpvReserved)
1784 {
1785 switch (dwReason)
1786 {
1787 case DLL_PROCESS_ATTACH:
1788 hDllInstance = hinstDLL;
1789 DisableThreadLibraryCalls(hinstDLL);
1790 break;
1791
1792 case DLL_PROCESS_DETACH:
1793 break;
1794 }
1795 return TRUE;
1796 }
1797
1798