* Sync up to trunk head (r64995).
[reactos.git] / dll / win32 / advapi32 / sec / ac.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/sec/ac.c
5 * PURPOSE: ACL/ACE functions
6 */
7
8 #include <advapi32.h>
9 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
10
11 /* --- ACE --- */
12
13 /*
14 * @implemented
15 */
16 BOOL
17 WINAPI
18 AddAccessAllowedObjectAce(PACL pAcl,
19 DWORD dwAceRevision,
20 DWORD AceFlags,
21 DWORD AccessMask,
22 GUID *ObjectTypeGuid,
23 GUID *InheritedObjectTypeGuid,
24 PSID pSid)
25 {
26 NTSTATUS Status;
27
28 Status = RtlAddAccessAllowedObjectAce(pAcl,
29 dwAceRevision,
30 AceFlags,
31 AccessMask,
32 ObjectTypeGuid,
33 InheritedObjectTypeGuid,
34 pSid);
35 if (!NT_SUCCESS(Status))
36 {
37 SetLastError(RtlNtStatusToDosError(Status));
38 return FALSE;
39 }
40
41 return TRUE;
42 }
43
44 /*
45 * @implemented
46 */
47 BOOL
48 WINAPI
49 AddAccessDeniedObjectAce(PACL pAcl,
50 DWORD dwAceRevision,
51 DWORD AceFlags,
52 DWORD AccessMask,
53 GUID* ObjectTypeGuid,
54 GUID* InheritedObjectTypeGuid,
55 PSID pSid)
56 {
57 NTSTATUS Status;
58
59 Status = RtlAddAccessDeniedObjectAce(pAcl,
60 dwAceRevision,
61 AceFlags,
62 AccessMask,
63 ObjectTypeGuid,
64 InheritedObjectTypeGuid,
65 pSid);
66 if (!NT_SUCCESS(Status))
67 {
68 SetLastError(RtlNtStatusToDosError(Status));
69 return FALSE;
70 }
71
72 return TRUE;
73 }
74
75 /*
76 * @implemented
77 */
78 BOOL
79 WINAPI
80 AddAuditAccessObjectAce(PACL pAcl,
81 DWORD dwAceRevision,
82 DWORD AceFlags,
83 DWORD AccessMask,
84 GUID *ObjectTypeGuid,
85 GUID *InheritedObjectTypeGuid,
86 PSID pSid,
87 BOOL bAuditSuccess,
88 BOOL bAuditFailure)
89 {
90 NTSTATUS Status;
91
92 Status = RtlAddAuditAccessObjectAce(pAcl,
93 dwAceRevision,
94 AceFlags,
95 AccessMask,
96 ObjectTypeGuid,
97 InheritedObjectTypeGuid,
98 pSid,
99 bAuditSuccess,
100 bAuditFailure);
101 if (!NT_SUCCESS(Status))
102 {
103 SetLastError(RtlNtStatusToDosError(Status));
104 return FALSE;
105 }
106
107 return TRUE;
108 }
109
110 /*
111 * @implemented
112 */
113 DWORD
114 WINAPI
115 GetInheritanceSourceW(LPWSTR pObjectName,
116 SE_OBJECT_TYPE ObjectType,
117 SECURITY_INFORMATION SecurityInfo,
118 BOOL Container,
119 GUID **pObjectClassGuids OPTIONAL,
120 DWORD GuidCount,
121 PACL pAcl,
122 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL,
123 PGENERIC_MAPPING pGenericMapping,
124 PINHERITED_FROMW pInheritArray)
125 {
126 DWORD ErrorCode;
127
128 ErrorCode = CheckNtMartaPresent();
129 if (ErrorCode == ERROR_SUCCESS)
130 {
131 /* call the MARTA provider */
132 ErrorCode = AccGetInheritanceSource(pObjectName,
133 ObjectType,
134 SecurityInfo,
135 Container,
136 pObjectClassGuids,
137 GuidCount,
138 pAcl,
139 pfnArray,
140 pGenericMapping,
141 pInheritArray);
142 }
143
144 return ErrorCode;
145 }
146
147
148 /*
149 * @unimplemented
150 */
151 DWORD
152 WINAPI
153 GetInheritanceSourceA(LPSTR pObjectName,
154 SE_OBJECT_TYPE ObjectType,
155 SECURITY_INFORMATION SecurityInfo,
156 BOOL Container,
157 GUID **pObjectClassGuids OPTIONAL,
158 DWORD GuidCount,
159 PACL pAcl,
160 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL,
161 PGENERIC_MAPPING pGenericMapping,
162 PINHERITED_FROMA pInheritArray)
163 {
164 /* That's all this function does, at least up to w2k3... Even MS was too
165 lazy to implement it... */
166 return ERROR_CALL_NOT_IMPLEMENTED;
167 }
168
169
170 /*
171 * @implemented
172 */
173 DWORD
174 WINAPI
175 FreeInheritedFromArray(PINHERITED_FROMW pInheritArray,
176 USHORT AceCnt,
177 PFN_OBJECT_MGR_FUNCTS pfnArray OPTIONAL)
178 {
179 DWORD ErrorCode;
180
181 ErrorCode = CheckNtMartaPresent();
182 if (ErrorCode == ERROR_SUCCESS)
183 {
184 /* call the MARTA provider */
185 ErrorCode = AccFreeIndexArray(pInheritArray,
186 AceCnt,
187 pfnArray);
188 }
189
190 return ErrorCode;
191 }
192
193
194 /*
195 * @implemented
196 */
197 DWORD
198 WINAPI
199 SetEntriesInAclW(ULONG cCountOfExplicitEntries,
200 PEXPLICIT_ACCESS_W pListOfExplicitEntries,
201 PACL OldAcl,
202 PACL *NewAcl)
203 {
204 DWORD ErrorCode;
205
206 if (!NewAcl)
207 {
208 return ERROR_INVALID_PARAMETER;
209 }
210
211 ErrorCode = CheckNtMartaPresent();
212 if (ErrorCode == ERROR_SUCCESS)
213 {
214 /* call the MARTA provider */
215 ErrorCode = AccRewriteSetEntriesInAcl(cCountOfExplicitEntries,
216 pListOfExplicitEntries,
217 OldAcl,
218 NewAcl);
219 }
220
221 return ErrorCode;
222 }
223
224
225 static DWORD
226 InternalTrusteeAToW(IN PTRUSTEE_A pTrusteeA,
227 OUT PTRUSTEE_W *pTrusteeW)
228 {
229 TRUSTEE_FORM TrusteeForm;
230 INT BufferSize = 0;
231 PSTR lpStr;
232 DWORD ErrorCode = ERROR_SUCCESS;
233
234 //ASSERT(sizeof(TRUSTEE_W) == sizeof(TRUSTEE_A));
235
236 TrusteeForm = GetTrusteeFormA(pTrusteeA);
237 switch (TrusteeForm)
238 {
239 case TRUSTEE_IS_NAME:
240 {
241 /* directly copy the array, this works as the size of the EXPLICIT_ACCESS_A
242 structure matches the size of the EXPLICIT_ACCESS_W version */
243 lpStr = GetTrusteeNameA(pTrusteeA);
244 if (lpStr != NULL)
245 BufferSize = strlen(lpStr) + 1;
246
247 *pTrusteeW = RtlAllocateHeap(RtlGetProcessHeap(),
248 0,
249 sizeof(TRUSTEE_W) + (BufferSize * sizeof(WCHAR)));
250 if (*pTrusteeW != NULL)
251 {
252 RtlCopyMemory(*pTrusteeW,
253 pTrusteeA,
254 FIELD_OFFSET(TRUSTEE_A,
255 ptstrName));
256
257 if (lpStr != NULL)
258 {
259 (*pTrusteeW)->ptstrName = (PWSTR)((*pTrusteeW) + 1);
260
261 /* convert the trustee's name */
262 if (MultiByteToWideChar(CP_ACP,
263 0,
264 lpStr,
265 -1,
266 (*pTrusteeW)->ptstrName,
267 BufferSize) == 0)
268 {
269 goto ConvertErr;
270 }
271 }
272 else
273 {
274 RtlFreeHeap(RtlGetProcessHeap(),
275 0,
276 *pTrusteeW);
277 goto NothingToConvert;
278 }
279 }
280 else
281 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
282 break;
283 }
284
285 case TRUSTEE_IS_OBJECTS_AND_NAME:
286 {
287 POBJECTS_AND_NAME_A oanA = (POBJECTS_AND_NAME_A)GetTrusteeNameA(pTrusteeA);
288 POBJECTS_AND_NAME_W oan;
289 PWSTR StrBuf;
290
291 /* calculate the size needed */
292 if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
293 oanA->InheritedObjectTypeName != NULL)
294 {
295 BufferSize = strlen(oanA->InheritedObjectTypeName) + 1;
296 }
297 if (oanA->ptstrName != NULL)
298 {
299 BufferSize += strlen(oanA->ptstrName) + 1;
300 }
301
302 *pTrusteeW = RtlAllocateHeap(RtlGetProcessHeap(),
303 0,
304 sizeof(TRUSTEE_W) + sizeof(OBJECTS_AND_NAME_W) +
305 (BufferSize * sizeof(WCHAR)));
306
307 if (*pTrusteeW != NULL)
308 {
309 oan = (POBJECTS_AND_NAME_W)((*pTrusteeW) + 1);
310 StrBuf = (PWSTR)(oan + 1);
311
312 /* copy over the parts of the TRUSTEE structure that don't need
313 to be touched */
314 RtlCopyMemory(*pTrusteeW,
315 pTrusteeA,
316 FIELD_OFFSET(TRUSTEE_A,
317 ptstrName));
318
319 (*pTrusteeW)->ptstrName = (LPWSTR)oan;
320
321 /* convert the OBJECTS_AND_NAME_A structure */
322 oan->ObjectsPresent = oanA->ObjectsPresent;
323 oan->ObjectType = oanA->ObjectType;
324
325 if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
326 oanA->InheritedObjectTypeName != NULL)
327 {
328 /* convert inherited object type name */
329 BufferSize = strlen(oanA->InheritedObjectTypeName) + 1;
330
331 if (MultiByteToWideChar(CP_ACP,
332 0,
333 oanA->InheritedObjectTypeName,
334 -1,
335 StrBuf,
336 BufferSize) == 0)
337 {
338 goto ConvertErr;
339 }
340 oan->InheritedObjectTypeName = StrBuf;
341
342 StrBuf += BufferSize;
343 }
344 else
345 oan->InheritedObjectTypeName = NULL;
346
347 if (oanA->ptstrName != NULL)
348 {
349 /* convert the trustee name */
350 BufferSize = strlen(oanA->ptstrName) + 1;
351
352 if (MultiByteToWideChar(CP_ACP,
353 0,
354 oanA->ptstrName,
355 -1,
356 StrBuf,
357 BufferSize) == 0)
358 {
359 goto ConvertErr;
360 }
361 oan->ptstrName = StrBuf;
362 }
363 else
364 oan->ptstrName = NULL;
365 }
366 else
367 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
368 break;
369 }
370
371 default:
372 {
373 NothingToConvert:
374 /* no need to convert anything to unicode */
375 *pTrusteeW = (PTRUSTEE_W)pTrusteeA;
376 break;
377 }
378 }
379
380 return ErrorCode;
381
382 ConvertErr:
383 ErrorCode = GetLastError();
384
385 /* cleanup */
386 RtlFreeHeap(RtlGetProcessHeap(),
387 0,
388 *pTrusteeW);
389
390 return ErrorCode;
391 }
392
393
394 static __inline VOID
395 InternalFreeConvertedTrustee(IN PTRUSTEE_W pTrusteeW,
396 IN PTRUSTEE_A pTrusteeA)
397 {
398 if ((PVOID)pTrusteeW != (PVOID)pTrusteeA)
399 {
400 RtlFreeHeap(RtlGetProcessHeap(),
401 0,
402 pTrusteeW);
403 }
404 }
405
406
407 static DWORD
408 InternalExplicitAccessAToW(IN ULONG cCountOfExplicitEntries,
409 IN PEXPLICIT_ACCESS_A pListOfExplicitEntriesA,
410 OUT PEXPLICIT_ACCESS_W *pListOfExplicitEntriesW)
411 {
412 TRUSTEE_FORM TrusteeForm;
413 SIZE_T Size;
414 ULONG i;
415 ULONG ObjectsAndNameCount = 0;
416 PEXPLICIT_ACCESS_W peaw = NULL;
417 DWORD ErrorCode = ERROR_SUCCESS;
418 LPSTR lpStr;
419
420 /* NOTE: This code assumes that the size of the TRUSTEE_A and TRUSTEE_W structure matches! */
421 //ASSERT(sizeof(TRUSTEE_A) == sizeof(TRUSTEE_W));
422
423 if (cCountOfExplicitEntries != 0)
424 {
425 /* calculate the size needed */
426 Size = cCountOfExplicitEntries * sizeof(EXPLICIT_ACCESS_W);
427 for (i = 0; i != cCountOfExplicitEntries; i++)
428 {
429 TrusteeForm = GetTrusteeFormA(&pListOfExplicitEntriesA[i].Trustee);
430
431 switch (TrusteeForm)
432 {
433 case TRUSTEE_IS_NAME:
434 {
435 lpStr = GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee);
436 if (lpStr != NULL)
437 Size += (strlen(lpStr) + 1) * sizeof(WCHAR);
438 break;
439 }
440
441 case TRUSTEE_IS_OBJECTS_AND_NAME:
442 {
443 POBJECTS_AND_NAME_A oan = (POBJECTS_AND_NAME_A)GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee);
444
445 if ((oan->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
446 oan->InheritedObjectTypeName != NULL)
447 {
448 Size += (strlen(oan->InheritedObjectTypeName) + 1) * sizeof(WCHAR);
449 }
450
451 if (oan->ptstrName != NULL)
452 Size += (strlen(oan->ptstrName) + 1) * sizeof(WCHAR);
453
454 ObjectsAndNameCount++;
455 break;
456 }
457
458 default:
459 break;
460 }
461 }
462
463 /* allocate the array */
464 peaw = RtlAllocateHeap(RtlGetProcessHeap(),
465 0,
466 Size);
467 if (peaw != NULL)
468 {
469 INT BufferSize;
470 POBJECTS_AND_NAME_W oan = (POBJECTS_AND_NAME_W)(peaw + cCountOfExplicitEntries);
471 LPWSTR StrBuf = (LPWSTR)(oan + ObjectsAndNameCount);
472
473 /* convert the array to unicode */
474 for (i = 0; i != cCountOfExplicitEntries; i++)
475 {
476 peaw[i].grfAccessPermissions = pListOfExplicitEntriesA[i].grfAccessPermissions;
477 peaw[i].grfAccessMode = pListOfExplicitEntriesA[i].grfAccessMode;
478 peaw[i].grfInheritance = pListOfExplicitEntriesA[i].grfInheritance;
479
480 /* convert or copy the TRUSTEE structure */
481 TrusteeForm = GetTrusteeFormA(&pListOfExplicitEntriesA[i].Trustee);
482 switch (TrusteeForm)
483 {
484 case TRUSTEE_IS_NAME:
485 {
486 lpStr = GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee);
487 if (lpStr != NULL)
488 {
489 /* convert the trustee name */
490 BufferSize = strlen(lpStr) + 1;
491
492 if (MultiByteToWideChar(CP_ACP,
493 0,
494 lpStr,
495 -1,
496 StrBuf,
497 BufferSize) == 0)
498 {
499 goto ConvertErr;
500 }
501 peaw[i].Trustee.ptstrName = StrBuf;
502
503 StrBuf += BufferSize;
504 }
505 else
506 goto RawTrusteeCopy;
507
508 break;
509 }
510
511 case TRUSTEE_IS_OBJECTS_AND_NAME:
512 {
513 POBJECTS_AND_NAME_A oanA = (POBJECTS_AND_NAME_A)GetTrusteeNameA(&pListOfExplicitEntriesA[i].Trustee);
514
515 /* copy over the parts of the TRUSTEE structure that don't need
516 to be touched */
517 RtlCopyMemory(&peaw[i].Trustee,
518 &pListOfExplicitEntriesA[i].Trustee,
519 FIELD_OFFSET(TRUSTEE_A,
520 ptstrName));
521
522 peaw[i].Trustee.ptstrName = (LPWSTR)oan;
523
524 /* convert the OBJECTS_AND_NAME_A structure */
525 oan->ObjectsPresent = oanA->ObjectsPresent;
526 oan->ObjectType = oanA->ObjectType;
527
528 if ((oanA->ObjectsPresent & ACE_INHERITED_OBJECT_TYPE_PRESENT) &&
529 oanA->InheritedObjectTypeName != NULL)
530 {
531 /* convert inherited object type name */
532 BufferSize = strlen(oanA->InheritedObjectTypeName) + 1;
533
534 if (MultiByteToWideChar(CP_ACP,
535 0,
536 oanA->InheritedObjectTypeName,
537 -1,
538 StrBuf,
539 BufferSize) == 0)
540 {
541 goto ConvertErr;
542 }
543 oan->InheritedObjectTypeName = StrBuf;
544
545 StrBuf += BufferSize;
546 }
547 else
548 oan->InheritedObjectTypeName = NULL;
549
550 if (oanA->ptstrName != NULL)
551 {
552 /* convert the trustee name */
553 BufferSize = strlen(oanA->ptstrName) + 1;
554
555 if (MultiByteToWideChar(CP_ACP,
556 0,
557 oanA->ptstrName,
558 -1,
559 StrBuf,
560 BufferSize) == 0)
561 {
562 goto ConvertErr;
563 }
564 oan->ptstrName = StrBuf;
565
566 StrBuf += BufferSize;
567 }
568 else
569 oan->ptstrName = NULL;
570
571 /* move on to the next OBJECTS_AND_NAME_A structure */
572 oan++;
573 break;
574 }
575
576 default:
577 {
578 RawTrusteeCopy:
579 /* just copy over the TRUSTEE structure, they don't contain any
580 ansi/unicode specific data */
581 RtlCopyMemory(&peaw[i].Trustee,
582 &pListOfExplicitEntriesA[i].Trustee,
583 sizeof(TRUSTEE_A));
584 break;
585 }
586 }
587 }
588
589 ASSERT(ErrorCode == ERROR_SUCCESS);
590 *pListOfExplicitEntriesW = peaw;
591 }
592 else
593 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
594 }
595
596 return ErrorCode;
597
598 ConvertErr:
599 ErrorCode = GetLastError();
600
601 /* cleanup */
602 RtlFreeHeap(RtlGetProcessHeap(),
603 0,
604 peaw);
605
606 return ErrorCode;
607 }
608
609
610 /*
611 * @implemented
612 */
613 DWORD
614 WINAPI
615 SetEntriesInAclA(ULONG cCountOfExplicitEntries,
616 PEXPLICIT_ACCESS_A pListOfExplicitEntries,
617 PACL OldAcl,
618 PACL *NewAcl)
619 {
620 PEXPLICIT_ACCESS_W ListOfExplicitEntriesW = NULL;
621 DWORD ErrorCode;
622
623 ErrorCode = InternalExplicitAccessAToW(cCountOfExplicitEntries,
624 pListOfExplicitEntries,
625 &ListOfExplicitEntriesW);
626 if (ErrorCode == ERROR_SUCCESS)
627 {
628 ErrorCode = SetEntriesInAclW(cCountOfExplicitEntries,
629 ListOfExplicitEntriesW,
630 OldAcl,
631 NewAcl);
632
633 /* free the allocated array */
634 RtlFreeHeap(RtlGetProcessHeap(),
635 0,
636 ListOfExplicitEntriesW);
637 }
638
639 return ErrorCode;
640 }
641
642
643 /*
644 * @implemented
645 */
646 DWORD
647 WINAPI
648 GetExplicitEntriesFromAclW(PACL pacl,
649 PULONG pcCountOfExplicitEntries,
650 PEXPLICIT_ACCESS_W *pListOfExplicitEntries)
651 {
652 DWORD ErrorCode;
653
654 ErrorCode = CheckNtMartaPresent();
655 if (ErrorCode == ERROR_SUCCESS)
656 {
657 /* call the MARTA provider */
658 ErrorCode = AccRewriteGetExplicitEntriesFromAcl(pacl,
659 pcCountOfExplicitEntries,
660 pListOfExplicitEntries);
661 }
662
663 return ErrorCode;
664 }
665
666
667 /*
668 * @unimplemented
669 */
670 DWORD
671 WINAPI
672 GetEffectiveRightsFromAclW(IN PACL pacl,
673 IN PTRUSTEE_W pTrustee,
674 OUT PACCESS_MASK pAccessRights)
675 {
676 FIXME("%p %p %p - stub\n", pacl, pTrustee, pAccessRights);
677
678 *pAccessRights = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL;
679 return ERROR_SUCCESS;
680 }
681
682
683 /*
684 * @implemented
685 */
686 DWORD
687 WINAPI
688 GetEffectiveRightsFromAclA(IN PACL pacl,
689 IN PTRUSTEE_A pTrustee,
690 OUT PACCESS_MASK pAccessRights)
691 {
692 PTRUSTEE_W pTrusteeW = NULL;
693 DWORD ErrorCode;
694
695 ErrorCode = InternalTrusteeAToW(pTrustee,
696 &pTrusteeW);
697 if (ErrorCode == ERROR_SUCCESS)
698 {
699 ErrorCode = GetEffectiveRightsFromAclW(pacl,
700 pTrusteeW,
701 pAccessRights);
702
703 InternalFreeConvertedTrustee(pTrusteeW,
704 pTrustee);
705 }
706 else
707 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
708
709 return ErrorCode;
710 }
711
712
713 /*
714 * @unimplemented
715 */
716 DWORD
717 WINAPI
718 GetAuditedPermissionsFromAclW(IN PACL pacl,
719 IN PTRUSTEE_W pTrustee,
720 OUT PACCESS_MASK pSuccessfulAuditedRights,
721 OUT PACCESS_MASK pFailedAuditRights)
722 {
723 FIXME("%s() not implemented!\n", __FUNCTION__);
724 return ERROR_CALL_NOT_IMPLEMENTED;
725 }
726
727
728 /*
729 * @implemented
730 */
731 DWORD
732 WINAPI
733 GetAuditedPermissionsFromAclA(IN PACL pacl,
734 IN PTRUSTEE_A pTrustee,
735 OUT PACCESS_MASK pSuccessfulAuditedRights,
736 OUT PACCESS_MASK pFailedAuditRights)
737 {
738 PTRUSTEE_W pTrusteeW = NULL;
739 DWORD ErrorCode;
740
741 ErrorCode = InternalTrusteeAToW(pTrustee,
742 &pTrusteeW);
743 if (ErrorCode == ERROR_SUCCESS)
744 {
745 ErrorCode = GetAuditedPermissionsFromAclW(pacl,
746 pTrusteeW,
747 pSuccessfulAuditedRights,
748 pFailedAuditRights);
749
750 InternalFreeConvertedTrustee(pTrusteeW,
751 pTrustee);
752 }
753 else
754 ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
755
756 return ErrorCode;
757 }
758
759 /* EOF */