File Coverage

blib/lib/Win32/Security/ACE.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             #############################################################################
2             #
3             # Win32::Security::ACE - Win32 ACE manipulation
4             #
5             # Author: Toby Ovod-Everett
6             #
7             #############################################################################
8             # Copyright 2003, 2004 Toby Ovod-Everett. All rights reserved
9             #
10             # This program is free software; you can redistribute it and/or modify it
11             # under the same terms as Perl itself.
12             #
13             # For comments, questions, bugs or general interest, feel free to
14             # contact Toby Ovod-Everett at toby@ovod-everett.org
15             #############################################################################
16            
17             =head1 NAME
18            
19             C - Win32 ACE manipulation
20            
21             =head1 SYNOPSIS
22            
23             use Win32::Security::ACE;
24            
25             my $ace = Win32::Security::ACE->new('FILE', $rawace);
26             my $ace2 = Win32::Security::ACE->new('FILE', $type, $flags, $mask, $trustee);
27             my $ace3 = Win32::Security::ACE->new('FILE', $type, $flags, $mask, $sid);
28            
29             $ace->objectType();
30            
31             $ace->aceType();
32             $ace->aceFlags();
33             $ace->accessMask();
34             $ace->sid();
35             $ace->trustee();
36            
37             $ace->explainAceFlags();
38             $ace->explainAccessMask();
39            
40             $ace->rawAce();
41             $ace->rawAceType();
42             $ace->rawAceFlags();
43             $ace->rawAccessMask();
44            
45             my(@container_inheritable_aces) = $ace->inheritable('CONTAINER');
46             my(@object_inheritable_aces) = $ace->inheritable('OBJECT');
47            
48             =head1 DESCRIPTION
49            
50             C and its subclasses provide an interface for interacting
51             with Win32 ACEs (Access Control Entries). The subclasses allow for variation in
52             mask behavior (different privileges apply to files than apply to registry keys
53             and so forth) and for variation in ACE behavior (C varieties).
54            
55             C uses the flyweight design pattern in conjunction with an
56             in-memory cache of demand-computed properties. The result is that parsing of
57             ACEs is only done once for each unique ACE, and that the ACE objects themselves
58             are very lightweight. Double-indirection is used in the ACE objects to provide
59             for mutability without invalidating the cache.
60            
61             =head2 Installation instructions
62            
63             This installs as part of C. See
64             C for more information.
65            
66             It depends upon C and C, which should be
67             installable via PPM or available on CPAN. It also depends upon
68             C and C , which are installed as
69             part of C.
70            
71            
72             =head1 ARCHITECTURE
73            
74             C uses some OO tricks to boost performance and clean up
75             the design. Here's a quick overview of the internal architecture, should you
76             care! It is possible to use C objects without
77             understanding or reading any of this, because the public interface is designed
78             to hide as much of the details as possible. After all, that's the point of OO
79             design. If, however, you want to boost performance or to muck about in the
80             internals, it's worth understanding how things were done.
81            
82             =head2 Class Structure
83            
84             C uses multiple inheritance in a diamond pattern. This
85             was deemed to be the best solution to an otherwise ugly situation.
86            
87             Each ACE comes in a variety of forms - six at current count - and some of these
88             forms (notably the C varieties) use a different internal
89             structure. While the code doesn't currently support the C
90             varieties, it was important to architect the code to support that for future
91             expansion.
92            
93             Each ACE can be applied to a wide variety of Named Objects as well. For better
94             or worse, the behavior of the Access Masks for Named Objects varies according to
95             the type of Named Object (think files vs. Active Directory objects). This
96             behavioral variation extends to the realm of applying inherited GENERIC Access
97             Masks to objects.
98            
99             Much internal debate (I love arguing with myself) was expended over attempting
100             to reconcile these two orthogonal forms of variation without multiple
101             inheritance before deciding to just bite the bullet.
102            
103             The obvious ugliness is that C
104             classes have to be created. Luckily I'd already made
105             C dependent upon C, so it was
106             deemed acceptable to make C and C
107             dependent upon it as well.
108            
109             With that in mind, the base class hierarchy looks like this:
110            
111             =over 4
112            
113             =item * C
114            
115             Base class of everything. Includes C, C, C, C,
116             and the C methods.
117            
118             =over 4
119            
120             =item * C
121            
122             Abstract base class for behavior linked to the ACE type. This includes the
123             C, C, C, C, C, and
124             C methods. All of the direct subclasses of C<_AceType> are
125             abstract as well. The package names have been collapsed by leaving out
126             C<_AceType> to keep things manageable.
127            
128            
129             =over 4
130            
131             =item * C
132            
133             =item * C
134            
135             =item * C
136            
137             =back
138            
139             =item * C
140            
141             Abstract base class for behavior linked to the Named Object type. This includes
142             the C and C methods. In addition, as will later
143             be discussed, each of the following classes is responsible for storing the
144             cached instance data for all ACEs they run into. Just like in C<_AceType>, all
145             of the direct subclasses of C<_ObjectType> are abstract as well and the package
146             names have been collapsed.
147            
148            
149             =over 4
150            
151             =item * C
152            
153             =back
154            
155             =back
156            
157             =back
158            
159             The concrete classes are named C
160             (i.e. C) and
161             inherit from both the C and
162             C classes in that order. The concrete classes
163             are automatically generated using C.
164            
165            
166             =head2 Flyweight Objects w/ Cached Demand-Computed Properties
167            
168             On the typical computer systems, there are very few unique ACEs. There may be
169             hundred or thousands, but usually there are orders of magnitude fewer ACEs than
170             there are objects to which they are applied. In order to reduce the computation
171             involved in analyzing them, C caches all the information
172             computed about each ACE in a central store (actually, multiple central stores -
173             one for each Named Object type) based on the binary form (C). The
174             object returned by a call to C is a reference to a reference to the hash
175             for that C in the central store. Because it isn't a direct reference to
176             the hash, it is possible to switch which hash the object points to on the fly.
177             This allows the C objects to be mutable while maintaining
178             the immutability of the central store. It also makes each individual
179             C object incredibly lightweight, since it is only composed
180             of a single blessed scalar. The properties are computed as needed, but the
181             results are cached in the central store.
182            
183             For instance, once C has been computed for a given C,
184             it can be found from the object as C<< $$self->{explainAccessMask} >>. This
185             should be used with care, although in some instances it is possible to reduce
186             the number of method calls (should this be necessary for performance reasons) by
187             making calls like so:
188            
189             $$ace->{explainAccessMask} || $ace->explainAccessMask();
190            
191             That provides a fail-safe should the C value have not yet
192             been computed while eliminating the method call if it has been.
193            
194             In order to defend against accidental manipulation, return values from the calls
195             (although not from the direct access, obviously) are deep-copied one layer deep.
196             That means that the results of C<< $ace->explainAccessMask() >> can be safely
197             manipulated without harming the ACE, but that the results of C<<
198             $$ace->{explainAccessMask} >> should be treated as read-only.
199             C objects returned are Cd (using inlined code to
200             reduce the performance hit). The values returned from the C calls are
201             not cloned, however, so be careful there.
202            
203             =cut
204            
205 3     3   887 use Carp qw();
  3         6  
  3         66  
206 3     3   1283 use Class::Prototyped '0.98';
  3         12248  
  3         19  
207 3     3   3337 use Data::BitMask '0.13';
  3         8516  
  3         89  
208 3     3   4196 use Data::Dumper;
  3         49217  
  3         225  
209 3     3   2065 use Win32::Security::Raw;
  0            
  0            
210             use Win32::Security::SID;
211            
212             use strict;
213            
214             BEGIN {
215             Class::Prototyped->newPackage('Win32::Security::ACE');
216            
217             package Win32::Security::ACE; #Added to ensure presence in META.yml
218            
219             Win32::Security::ACE->reflect->addSlot(
220             objectTypes => [
221             'SE_FILE_OBJECT',
222             'SE_REGISTRY_KEY',
223             ],
224             );
225            
226             Win32::Security::ACE->reflect->addSlot(
227             aceTypes => [
228             'ACCESS_ALLOWED_ACE_TYPE',
229             'ACCESS_DENIED_ACE_TYPE',
230             'SYSTEM_AUDIT_ACE_TYPE',
231             ],
232             );
233            
234             Win32::Security::ACE->newPackage('Win32::Security::ACE::_ObjectType');
235             Win32::Security::ACE->newPackage('Win32::Security::ACE::_AceType');
236            
237             foreach my $aceType (@{Win32::Security::ACE->aceTypes()}) {
238             Win32::Security::ACE::_AceType->newPackage("Win32::Security::ACE::$aceType",
239             aceType => $aceType,
240             );
241             }
242            
243             foreach my $objectType (@{Win32::Security::ACE->objectTypes()}) {
244             my $objectPackage = "Win32::Security::ACE::$objectType";
245             Win32::Security::ACE::_ObjectType->newPackage($objectPackage,
246             objectType => $objectType,
247             _rawAceCache => {},
248             );
249            
250             foreach my $aceType (@{Win32::Security::ACE->aceTypes()}) {
251             Class::Prototyped->newPackage("$objectPackage\::$aceType",
252             'objectPackage*' => $objectPackage,
253             'acePackage*' => "Win32::Security::ACE::$aceType"
254             );
255             }
256             }
257             }
258            
259             =head1 Method Reference
260            
261             =head2 C
262            
263             Creates a new C object.
264            
265             The various calling forms are:
266            
267             =over 4
268            
269             =item * C<< Win32::Security::ACE->new($objectType, $rawAce) >>
270            
271             =item * C<< Win32::Security::ACE->new($objectType, $aceType, @aceParams) >>
272            
273             =item * C<< "Win32::Security::ACE::$objectType"->new($rawAce) >>
274            
275             =item * C<< "Win32::Security::ACE::$objectType"->new($aceType, @aceParams) >>
276            
277             =item * C<< "Win32::Security::ACE::$objectType\::$aceType"->new($rawAce) >>
278            
279             =item * C<< "Win32::Security::ACE::$objectType\::$aceType"->new(@aceParams) >>
280            
281             =item * C<< $ace_object->new($rawAce) >>
282            
283             =item * C<< $ace_object->new(@aceParams) >>
284            
285             =back
286            
287             Note that when using C<$objectType> and C<$aceType> in the package name, the
288             values need to be canonicalized (i.e. C, not the alias C).
289             Also note that the C<$aceType> is extractable from the C<$rawAce>. When those
290             values are passed as part of the parameter list, any of the valid aliases are
291             permitted. If the C<$objectType> or C<$aceType> has already been canonicalized,
292             improved performance can be realized by making the call on the more
293             fully-qualified package name and thus avoiding the calls to redo the
294             canonicalization. It is important that if C<$aceType> is specified for a
295             C<$rawAce> that the values match. The backslash preceding the final C<::> in
296             the final two class name calls is a fast way of ensuring that C<$objectType>
297             rather than C<$objectType::> is the interpolated variable name.
298            
299             For C, C, and
300             C, the C<@aceParams> array consists of C,
301             C, and either the C or C. The C,
302             C, and C can be passed as integers or in any acceptable
303             format for C (i.e. C<'|'> separated constants in a string, an
304             anonmous array of constants, or an anonymous hash of constants). See
305             C for more information.
306            
307             =cut
308            
309             Win32::Security::ACE->reflect->addSlot(
310             new => sub {
311             my $source = shift;
312            
313             my $class = ref($source) ? ref($source) : $source;
314            
315             $class =~ /^Win32::Security::ACE(?:::([^:]+)(?:::([^:]+))?)?$/ or Carp::croak("Win32::Security::ACL::new unable to parse classname '$class'.");
316             my($objectType, $aceType) = ($1, $2);
317             $objectType ||= Win32::Security::ACE->dbmObjectType()->explain_const(shift);
318             $objectType eq '_ObjectType' and Carp::croak('Win32::Security::ACE::_ObjectType is abstract!.');
319            
320             my $rawAce;
321            
322             if (scalar(@_) == 1) {
323             $rawAce = $_[0];
324             } else {
325             $aceType ||= $class->dbmAceType()->explain_const(shift);
326             $rawAce = "Win32::Security::ACE::$objectType\::$aceType"->buildRawAce(@_);
327             }
328            
329             my $_rawAceCache = "Win32::Security::ACE::$objectType"->_rawAceCache();
330             my $thing = $_rawAceCache->{$rawAce};
331             unless ($thing) {
332             $thing = $_rawAceCache->{$rawAce} = {};
333             $thing->{rawAce} = $rawAce;
334             $thing->{aceType} = $aceType || $class->dbmAceType()->explain_const(unpack("C", $rawAce));;
335             }
336            
337             my $self = \$thing;
338             bless $self, "Win32::Security::ACE::$objectType\::$thing->{aceType}";
339             return $self;
340             },
341             );
342            
343            
344             =head2 C
345            
346             This creates a new C object that is identical in all
347             forms, except for identity, to the original object. Because of the flyweight
348             design pattern, this is a very inexpensive operation. However, should you wish
349             to avoid the overhead of a method call, you can inline the code like so:
350            
351             bless(\(my $o = ${$obj}), ref($obj));
352            
353             Basically, it derefences the scalar reference, assigns it to a temporary
354             lexical, creates a reference to that, and then blesses it into the original
355             package. Nifty, eh? Syntax stolen (with a few modifications) from
356             C output.
357            
358             =cut
359            
360             Win32::Security::ACE->reflect->addSlot(
361             clone => sub {
362             bless(\(my $o = ${$_[0]}), ref($_[0]));
363             },
364             );
365            
366            
367             =head2 C
368            
369             This returns a dump of the C object in a format useful for
370             debugging.
371            
372             =cut
373            
374             Win32::Security::ACE->reflect->addSlot(
375             dump => sub {
376             my $self = shift;
377             my(%params) = @_;
378            
379             my $args = join(", ", map { $_ ne '' ? "'$_'" : 'undef' }
380             $params{hide_objectType} ? () : ($self->objectType()),
381             $self->aceType(),
382             join("|", sort keys %{$self->explainAceFlags()}),
383             join("|", sort keys %{$self->explainAccessMask()}),
384             $self->trustee() || 'undef',
385             );
386             $params{hide_instantiation} and return $args;
387             return "Win32::Security::ACE->new($args)";
388             },
389             );
390            
391            
392             =head2 C
393            
394             Returns the binary string form of the ACE. If passed a value, changes
395             the binary string form of the ACE to the new value and returns C<$self>.
396            
397             =cut
398            
399             Win32::Security::ACE->reflect->addSlot(
400             rawAce => sub {
401             my $self = shift;
402             my $thing = $$self;
403            
404             if (scalar(@_)) {
405             my $new_self = $self->new($_[0]);
406             $$self = $$new_self;
407             return $self;
408             } else {
409             return $thing->{rawAce};
410             }
411             },
412             );
413            
414            
415             =head2 C
416            
417             Returns the C object for interacting with ACE Types. Standard
418             Win32 constants for C are supported along with several aliases. The
419             standard C constants are C,
420             C, C, C,
421             C, C,
422             C, C,
423             C, C,
424             C, C,
425             C, C,
426             C, and C.
427            
428             The aliases are:
429            
430             =over 4
431            
432             =item *
433            
434             C or C (C)
435            
436             =item *
437            
438             C or C (C)
439            
440             =item *
441            
442             C (C)
443            
444             =back
445            
446             =cut
447            
448             Win32::Security::ACE->reflect->addSlot(
449             dbmAceType => Data::BitMask->new(
450             ACCESS_ALLOWED_ACE_TYPE => 0x0,
451             ACCESS_DENIED_ACE_TYPE => 0x1,
452             SYSTEM_AUDIT_ACE_TYPE => 0x2,
453             SYSTEM_ALARM_ACE_TYPE => 0x3,
454             ACCESS_ALLOWED_COMPOUND_ACE_TYPE => 0x4,
455             ACCESS_ALLOWED_OBJECT_ACE_TYPE => 0x5,
456             ACCESS_DENIED_OBJECT_ACE_TYPE => 0x6,
457             SYSTEM_AUDIT_OBJECT_ACE_TYPE => 0x7,
458             SYSTEM_ALARM_OBJECT_ACE_TYPE => 0x8,
459            
460             ACCESS_MIN_MS_ACE_TYPE => 0x0,
461             ACCESS_MAX_MS_V2_ACE_TYPE => 0x3,
462             ACCESS_MAX_MS_V3_ACE_TYPE => 0x4,
463             ACCESS_MIN_MS_OBJECT_ACE_TYPE => 0x5,
464             ACCESS_MAX_MS_OBJECT_ACE_TYPE => 0x8,
465             ACCESS_MAX_MS_V4_ACE_TYPE => 0x8,
466             ACCESS_MAX_MS_ACE_TYPE => 0x8,
467            
468             ALLOWED => 0x0,
469             ALLOW => 0x0,
470             DENIED => 0x1,
471             DENY => 0x1,
472             AUDIT => 0x2,
473             ),
474             );
475            
476            
477             =head2 C
478            
479             Returns the C object for interacting with Named Object Types.
480             The standard Object Types are C, C,
481             C, C, C, C,
482             C, C, C, C,
483             and C.
484            
485             There are a number of aliases as well:
486            
487             =over 4
488            
489             =item *
490            
491             C (C)
492            
493             =item *
494            
495             C (C)
496            
497             =item *
498            
499             C (C)
500            
501             =item *
502            
503             C (C)
504            
505             =item *
506            
507             C (C)
508            
509             =item *
510            
511             C (C)
512            
513             =back
514            
515             =cut
516            
517             Win32::Security::ACE->reflect->addSlot(
518             dbmObjectType => &Win32::Security::SE_OBJECT_TYPE(),
519             );
520            
521            
522            
523            
524            
525             #### Win32::Security::ACE::_AceType Methods
526            
527             =head2 C
528            
529             Returns the integer form of the ACE Type. Useful for equality checks with other
530             calls to C.
531            
532             =cut
533            
534             foreach my $aceType (@{Win32::Security::ACE->aceTypes()}) {
535             "Win32::Security::ACE::$aceType"->reflect->addSlot(
536             rawAceType => Win32::Security::ACE->dbmAceType()->build_const($aceType),
537             );
538             }
539            
540             =head2 C
541            
542             Returns the C form of the ACE Type (i.e. a string
543             constant, such as C<'ACCESS_ALLOWED_ACE_TYPE'> or C<'ACCESS_DENIED_ACE_TYPE'>).
544            
545             =cut
546            
547             #no implementation - handled during package initiation
548            
549            
550             =head2 C
551            
552             Returns the C object for interacting with ACE Flags. Standard
553             Win32 constants for C are supported along with some aliases. The
554             standard C constants are C,
555             C, C, C,
556             C, C, and C.
557            
558             The aliases are:
559            
560             =over 4
561            
562             =item *
563            
564             C (C)
565            
566             =item *
567            
568             C or C (C)
569            
570             =item *
571            
572             C (C)
573            
574             =item *
575            
576             C (C)
577            
578             =item *
579            
580             C (C)
581            
582             =item *
583            
584             C (C)
585            
586             =item *
587            
588             C (C)
589            
590             =item *
591            
592             C (C)
593            
594             =back
595            
596             =cut
597            
598             Win32::Security::ACE::_AceType->reflect->addSlot(
599             dbmAceFlags => Data::BitMask->new(
600             OBJECT_INHERIT_ACE => 0x01,
601             CONTAINER_INHERIT_ACE => 0x02,
602             NO_PROPAGATE_INHERIT_ACE => 0x04,
603             INHERIT_ONLY_ACE => 0x08,
604             INHERITED_ACE => 0x10,
605             SUCCESSFUL_ACCESS_ACE_FLAG => 0x40,
606             FAILED_ACCESS_ACE_FLAG => 0x80,
607             ),
608             );
609            
610             Win32::Security::ACE::_AceType->dbmAceFlags()->add_constants(
611             SUBFOLDERS_AND_FILES_ONLY => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('CONTAINER_INHERIT_ACE INHERIT_ONLY_ACE OBJECT_INHERIT_ACE'),
612             FULL_INHERIT => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('CONTAINER_INHERIT_ACE OBJECT_INHERIT_ACE '),
613             FILES_ONLY => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('INHERIT_ONLY_ACE OBJECT_INHERIT_ACE'),
614             SUBFOLDERS_ONLY => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('CONTAINER_INHERIT_ACE INHERIT_ONLY_ACE'),
615             );
616            
617             Win32::Security::ACE::_AceType::dbmAceFlags()->add_constants(
618             FI => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('FULL_INHERIT'),
619             CI => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('CONTAINER_INHERIT_ACE'),
620             OI => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('OBJECT_INHERIT_ACE'),
621             IO => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('INHERIT_ONLY_ACE'),
622             NP => Win32::Security::ACE::_AceType->dbmAceFlags()->build_mask('NO_PROPAGATE_INHERIT_ACE'),
623             );
624            
625            
626             =head2 C
627            
628             Returns the integer form of the ACE Flags. Useful for equality checks with
629             other calls to C.
630            
631             If called with a passed parameter, mutates the ACE to that new aceFlags value.
632             All forms of aceFlags access accept all forms as parameters when used as a
633             setter.
634            
635             =cut
636            
637             Win32::Security::ACE::_AceType->reflect->addSlot(
638             rawAceFlags => sub {
639             my $self = shift;
640             my $thing = $$self;
641            
642             if (scalar(@_)) {
643             $self->rawAce($self->buildRawAceNamed(aceFlags => $_[0]));
644             return $self;
645             } else {
646             exists $thing->{rawAceFlags} or $self->_splitRawAce();
647             return $thing->{rawAceFlags};
648             }
649             },
650             );
651            
652            
653             =head2 C
654            
655             Returns the C form of the ACE Flags (i.e. a hash
656             containing all matching constants for the Flags mask of the ACE).
657            
658             If called with a passed parameter, mutates the ACE to that new aceFlags value.
659             All forms of aceFlags access accept all forms as parameters when used as a
660             setter.
661            
662             =cut
663            
664             Win32::Security::ACE::_AceType->reflect->addSlot(
665             aceFlags => sub {
666             my $self = shift;
667             my $thing = $$self;
668            
669             if (scalar(@_)) {
670             $self->rawAce($self->buildRawAceNamed(aceFlags => $_[0]));
671             return $self;
672             } else {
673             exists $thing->{aceFlags} or $thing->{aceFlags} = $self->dbmAceFlags()->break_mask($self->rawAceFlags());
674             return {%{$thing->{aceFlags}}};
675             }
676             },
677             );
678            
679            
680             =head2 C
681            
682             Returns the C form of the ACE Flags (i.e. a hash
683             containing a set of constants sufficient to recreate and explain the flags mask
684             of the ACE).
685            
686             If called with a passed parameter, mutates the ACE to that new aceFlags value.
687             All forms of aceFlags access accept all forms as parameters when used as a
688             setter.
689            
690             =cut
691            
692             Win32::Security::ACE::_AceType->reflect->addSlot(
693             explainAceFlags => sub {
694             my $self = shift;
695             my $thing = $$self;
696            
697             if (scalar(@_)) {
698             $self->rawAce($self->buildRawAceNamed(aceFlags => $_[0]));
699             return $self;
700             } else {
701             exists $thing->{explainAceFlags} or $thing->{explainAceFlags} = $self->dbmAceFlags->explain_mask($self->rawAceFlags());
702             return {%{$thing->{explainAceFlags}}};
703             }
704             },
705             );
706            
707            
708             =head2 C
709            
710             Returns the SID in binary form. Useful for equality checks with other SIDs.
711            
712             If called with a passed parameter, mutates the ACE to that new SID. Both C
713             and C accepts SID and Trustee names as passed parameters when used as a
714             setter.
715            
716             =cut
717            
718             Win32::Security::ACE::_AceType->reflect->addSlot(
719             sid => sub {
720             my $self = shift;
721             my $thing = $$self;
722            
723             if (scalar(@_)) {
724             $self->rawAce($self->buildRawAceNamed(trustee => $_[0]));
725             return $self;
726             } else {
727             exists $thing->{sid} or $self->_splitRawAce();
728             return $thing->{sid};
729             }
730             },
731             );
732            
733            
734             =head2 C
735            
736             Returns the Trustee for the SID as generated by
737             C.
738            
739             If called with a passed parameter, mutates the ACE to that new trustee. Both C
740             and C accepts SID and Trustee names as passed parameters when used as a
741             setter.
742            
743             =cut
744            
745             Win32::Security::ACE::_AceType->reflect->addSlot(
746             trustee => sub {
747             my $self = shift;
748             my $thing = $$self;
749            
750             if (scalar(@_)) {
751             $self->rawAce($self->buildRawAceNamed(trustee => $_[0]));
752             return $self;
753             } else {
754             exists $thing->{trustee} or $thing->{trustee} = &Win32::Security::SID::ConvertSidToName($self->sid());
755             return $thing->{trustee};
756             }
757             },
758             );
759            
760             =head2 C
761            
762             Creates a binary string ACE from parameters. This should B be called on
763             a full class (i.e. C). Each
764             implementation accepts different parameters.
765            
766             =over 4
767            
768             =cut
769            
770             Win32::Security::ACE::_AceType->reflect->addSlot(
771             buildRawAce => sub {
772             Carp::croak('Win32::Security::ACE::_AceType::buildRawAce is abstract.');
773             },
774             );
775            
776             =item C, C, C
777            
778             These accept C, C, and either C or C.
779            
780             =cut
781            
782             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->addSlot(
783             buildRawAce => sub {
784             my $class = shift;
785             my($aceFlags, $accessMask, $trustee) = @_;
786            
787             eval { $aceFlags = $class->dbmAceFlags()->build_mask($aceFlags); };
788             $@ and die "Unable to parse AceFlags value '$aceFlags': $@";
789             eval { $accessMask = $class->dbmAccessMask()->build_mask($accessMask); };
790             $@ and die "Unable to parse AccessMask value '$accessMask': $@";
791             my $sid;
792             if (defined $trustee) {
793             $sid = ($trustee =~ /^[\01-\03]/) ? $trustee : &Win32::Security::SID::ConvertNameToSid($trustee);
794             $sid or die "Unable to parse Trustee/SID value '$trustee'.";
795             }
796            
797             return pack("CCSL", $class->rawAceType(), $aceFlags, length($sid) + 8, $accessMask).$sid;
798             },
799             );
800            
801             Win32::Security::ACE::ACCESS_DENIED_ACE_TYPE->reflect->addSlot(
802             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->getSlot('buildRawAce'),
803             );
804            
805             Win32::Security::ACE::SYSTEM_AUDIT_ACE_TYPE->reflect->addSlot(
806             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->getSlot('buildRawAce'),
807             );
808            
809             =back
810            
811             =cut
812            
813            
814             =head2 C
815            
816             Creates a binary string ACE from named parameters. This should B be
817             called on a full class (i.e. C)
818             B on an existing ACE. Each implementation accepts different parameters. If
819             called on an existing ACE, missing parameters will be supplied from the existing
820             ACE. As an example, to create a new C value based on an existing ACE,
821             but with the Access Mask set to C:
822            
823             $ace->buildRawAceNamed(accessMask => 'READ');
824            
825             =over 4
826            
827             =cut
828            
829             Win32::Security::ACE::_AceType->reflect->addSlot(
830             buildRawAceNamed => sub {
831             Carp::croak('Win32::Security::ACE::_AceType::buildRawAceNamed is abstract.');
832             },
833             );
834            
835             =item C, C, C
836            
837             These accept C, C, and C (as either a SID or
838             Trustee name). The names are case-sensitive.
839            
840             =cut
841            
842             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->addSlot(
843             buildRawAceNamed => sub {
844             my $source = shift;
845             my(%params) = @_;
846            
847             my $class = ref($source) ? ref($source) : $source;
848            
849             my(@badkeys) = grep(!/^(?:aceFlags|accessMask|trustee)$/, keys %params);
850             @badkeys and die "Unable to handle named parameter(s) ".join(',', map {"'$_'"} sort @badkeys)." in call to buildRawAceNamed.\n";
851            
852             my $aceFlags = eval { exists $params{aceFlags} ? $class->dbmAceFlags()->build_mask($params{aceFlags}) : (ref($source) ? $source->rawAceFlags() : 0) ; };
853             $@ and die "Unable to parse AceFlags value '$params{aceFlags}': $@";
854             my $accessMask = eval { exists $params{accessMask} ? $class->dbmAccessMask()->build_mask($params{accessMask}) : (ref($source) ? $source->rawAccessMask() : 0); };
855             $@ and die "Unable to parse AccessMask value '$params{accessMask}': $@";
856            
857             my $sid;
858             if (exists $params{trustee}) {
859             if (defined $params{trustee}) {
860             $sid = ($params{trustee} =~ /^[\01-\03]/) ? $params{trustee} : &Win32::Security::SID::ConvertNameToSid($params{trustee});
861             $sid or die "Unable to parse Trustee/SID value '$params{trustee}'.";
862             }
863             } else {
864             $sid = ref($source) ? $source->sid() : undef;
865             }
866            
867             return pack("CCSL", $class->rawAceType(), $aceFlags, length($sid) + 8, $accessMask).$sid;
868             },
869             );
870            
871             Win32::Security::ACE::ACCESS_DENIED_ACE_TYPE->reflect->addSlot(
872             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->getSlot('buildRawAceNamed'),
873             );
874            
875             Win32::Security::ACE::SYSTEM_AUDIT_ACE_TYPE->reflect->addSlot(
876             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->getSlot('buildRawAceNamed'),
877             );
878            
879             =back
880            
881             =cut
882            
883            
884             ## _splitRawAce Methods
885            
886             Win32::Security::ACE::_AceType->reflect->addSlot(
887             _splitRawAce => sub {
888             Carp::croak('Win32::Security::ACE::_AceType::_splitRawAce is abstract.');
889             },
890             );
891            
892             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->addSlot(
893             _splitRawAce => sub {
894             my $self = shift;
895             my $thing = $$self;
896            
897             my $rawAce = $self->rawAce();
898             my($AceType, $AceFlags, $AceSize, $AccessMask) = unpack("CCSL", substr($rawAce, 0, 8));
899             $AceType == $self->rawAceType() or Carp::croak("AceType in raw ACE didn't match '".ref($self)."'.");
900             $thing->{rawAceFlags} = $AceFlags;
901             $thing->{rawAccessMask} = $AccessMask;
902             $thing->{sid} = substr($rawAce, 8, $AceSize-8);
903             },
904             );
905            
906             Win32::Security::ACE::ACCESS_DENIED_ACE_TYPE->reflect->addSlot(
907             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->getSlot('_splitRawAce'),
908             );
909            
910             Win32::Security::ACE::SYSTEM_AUDIT_ACE_TYPE->reflect->addSlot(
911             Win32::Security::ACE::ACCESS_ALLOWED_ACE_TYPE->reflect->getSlot('_splitRawAce'),
912             );
913            
914            
915             =head2 C
916            
917             Accepts a type (either C<'OBJECT'> or C<'CONTAINER'>) and calls
918             C or C as appropriate.
919            
920             Those methods return the list of ACEs that would be inherited by a newly created
921             child C or C if the parent has this ACE. In most cases,
922             there will be either none (non-inheritable ACE) or one (inheritable ACE) ACEs
923             returned. In the case of ACEs that use C permissions or that use
924             C, there may be two ACEs returned - one to implement the
925             permissions on that specific container, and the other to perpetuate the
926             inheritable ACE. In the case of an C ACE, the ACE that
927             implements the actual permissions on the container will be given a null SID.
928            
929             The methods take care of checking the flags to determine whether the ACE should
930             be inherited as well as adjusting the flags for any inherited ACE appropriately.
931            
932             Note that it is not sufficient to simply concatenate the ACEs of a DACL to
933             generate the inheritable DACL because Win2K and WinXP remove occluded
934             permissions (for instance, if an container has an inherited permission granting
935             C access to Domain Users and someone grants explicit fully-inheritable
936             C access to Domain Users to that container, child objects will not receive
937             the inherited C access because it is fully occluded by the also inherited
938             C access).
939            
940             =cut
941            
942             Win32::Security::ACE::_AceType->reflect->addSlot(
943             inheritable => sub {
944             my $self = shift;
945             my $thing = $$self;
946             my($type) = @_;
947            
948             ($type eq 'OBJECT' || $type eq 'CONTAINER') or Carp::croak("Need to pass OBJECT or CONTAINER to Win32::Security::ACE::inheritable.");
949            
950             my $call = "inheritable_$type";
951             exists $thing->{$call} and return(map {bless(\(my $o = $$_), ref($_))} @{$thing->{$call}});
952             return $self->$call();
953             },
954             );
955            
956             =head2 C
957            
958             See C for an explanation.
959            
960             =cut
961            
962             Win32::Security::ACE::_AceType->reflect->addSlot(
963             inheritable_CONTAINER => sub {
964             my $self = shift;
965             my $thing = $$self;
966             my($type) = @_;
967            
968             unless (exists $thing->{inheritable_CONTAINER}) {
969             my $aceFlags = $self->aceFlags();
970            
971             $thing->{inheritable_CONTAINER} = [];
972            
973             if ($aceFlags->{CONTAINER_INHERIT_ACE} || ($aceFlags->{OBJECT_INHERIT_ACE} && !$aceFlags->{NO_PROPAGATE_INHERIT_ACE})) {
974             my $rawCleansedAccessMask = $self->dbmAccessMask()->build_mask($self->cleansedAccessMask());
975             my $trustee = $self->trustee();
976            
977             if ($rawCleansedAccessMask == $self->rawAccessMask() && $trustee ne 'CREATOR OWNER') {
978             my $new_flags = {%$aceFlags};
979             $new_flags->{INHERITED_ACE} = 1;
980             $new_flags->{INHERIT_ONLY_ACE} = $aceFlags->{CONTAINER_INHERIT_ACE} ? 0 : 1;
981             if ($aceFlags->{NO_PROPAGATE_INHERIT_ACE}) {
982             $new_flags->{CONTAINER_INHERIT_ACE} = 0;
983             $new_flags->{OBJECT_INHERIT_ACE} = 0;
984             $new_flags->{NO_PROPAGATE_INHERIT_ACE} = 0;
985             }
986             push( @{$thing->{inheritable_CONTAINER}},
987             Win32::Security::ACE->new($self->objectType(), $self->rawAceType(), $new_flags, $rawCleansedAccessMask, $self->sid()) );
988             } else {
989             if ($aceFlags->{CONTAINER_INHERIT_ACE}) {
990             my $new_flags = {%$aceFlags};
991             $new_flags->{INHERITED_ACE} = 1;
992             $new_flags->{INHERIT_ONLY_ACE} = 0;
993             $new_flags->{OBJECT_INHERIT_ACE} = 0;
994             $new_flags->{CONTAINER_INHERIT_ACE} = 0;
995             $new_flags->{NO_PROPAGATE_INHERIT_ACE} = 0;
996             push( @{$thing->{inheritable_CONTAINER}},
997             Win32::Security::ACE->new($self->objectType(), $self->rawAceType(), $new_flags, $rawCleansedAccessMask, $trustee eq 'CREATOR OWNER' ? undef : $self->sid()) );
998             }
999            
1000             if (!$aceFlags->{NO_PROPAGATE_INHERIT_ACE}) {
1001             my $new_flags = {%$aceFlags};
1002             $new_flags->{INHERITED_ACE} = 1;
1003             $new_flags->{INHERIT_ONLY_ACE} = 1;
1004            
1005             push( @{$thing->{inheritable_CONTAINER}},
1006             Win32::Security::ACE->new($self->objectType(), $self->rawAceType(), $new_flags, $self->rawAccessMask(), $self->sid()) );
1007             }
1008             }
1009             }
1010            
1011             }
1012             return(map {bless(\(my $o = $$_), ref($_))} @{$thing->{inheritable_CONTAINER}});
1013             },
1014             );
1015            
1016             =head2 C
1017            
1018             See C for an explanation.
1019            
1020             =cut
1021            
1022             Win32::Security::ACE::_AceType->reflect->addSlot(
1023             inheritable_OBJECT => sub {
1024             my $self = shift;
1025             my $thing = $$self;
1026             my($type) = @_;
1027            
1028             unless (exists $thing->{inheritable_OBJECT}) {
1029             my $aceFlags = $self->aceFlags();
1030            
1031             $thing->{inheritable_OBJECT} = [];
1032            
1033             if ($aceFlags->{OBJECT_INHERIT_ACE}) {
1034             my $new_flags = {%{$aceFlags}};
1035            
1036             $new_flags->{CONTAINER_INHERIT_ACE} = 0;
1037             $new_flags->{OBJECT_INHERIT_ACE} = 0;
1038             $new_flags->{INHERIT_ONLY_ACE} = 0;
1039             $new_flags->{NO_PROPAGATE_INHERIT_ACE} = 0;
1040             $new_flags->{INHERITED_ACE} = 1;
1041            
1042             my $trustee = $self->trustee();
1043            
1044             push( @{$thing->{inheritable_OBJECT}},
1045             Win32::Security::ACE->new($self->objectType(), $self->rawAceType(), $new_flags, $self->cleansedAccessMask(), $trustee eq 'CREATOR OWNER' ? undef : $self->sid()) );
1046             }
1047             }
1048             return(map {bless(\(my $o = $$_), ref($_))} @{$thing->{inheritable_OBJECT}});
1049             },
1050             );
1051            
1052            
1053            
1054             #### Win32::Security::ACE::_ObjectType Methods
1055            
1056             =head2 C
1057            
1058             Returns the type of object to which the ACE is or should be attached.
1059            
1060             =cut
1061            
1062             #no implementation - handled during package initiation
1063            
1064            
1065             =head2 C
1066            
1067             Returns the C object for interacting with the Access Mask. The
1068             default is Win32 constants for Standard Rights. Some of the Object Types define
1069             additional rights. The Standard Rights are C, C,
1070             C, C, C, C,
1071             C, C, C,
1072             C, C, C,
1073             C, C, C, C, and
1074             C.
1075            
1076             =over 4
1077            
1078             =cut
1079            
1080             Win32::Security::ACE::_ObjectType->reflect->addSlot(
1081             dbmAccessMask => Data::BitMask->new(
1082             DELETE => 0x00010000,
1083             READ_CONTROL => 0x00020000,
1084             WRITE_DAC => 0x00040000,
1085             WRITE_OWNER => 0x00080000,
1086             SYNCHRONIZE => 0x00100000,
1087            
1088             STANDARD_RIGHTS_REQUIRED => 0x000F0000,
1089             STANDARD_RIGHTS_READ => 0x00020000,
1090             STANDARD_RIGHTS_WRITE => 0x00020000, #Note. This confuses the hell out of me.
1091             #Everything I've read reiterates it, though. STANDARD_RIGHTS_WRITE != WRITE_DAC.
1092             #I think it just means that you need to be able to read the DACL to write to the object.
1093             STANDARD_RIGHTS_EXECUTE => 0x00020000,
1094             STANDARD_RIGHTS_ALL => 0x001F0000,
1095            
1096             SPECIFIC_RIGHTS_ALL => 0x0000FFFF,
1097            
1098             ACCESS_SYSTEM_SECURITY => 0x01000000,
1099            
1100             MAXIMUM_ALLOWED => 0x02000000,
1101            
1102             GENERIC_READ => 0x80000000,
1103             GENERIC_WRITE => 0x40000000,
1104             GENERIC_EXECUTE => 0x20000000,
1105             GENERIC_ALL => 0x10000000,
1106             ),
1107             );
1108            
1109             =item C
1110            
1111             Win32 constants for both Standard Rights and File Rights, along with a number of
1112             aliases. The File Rights are C, C,
1113             C, C, C,
1114             C, C, C,
1115             C, C, C, C,
1116             C, C, C,
1117             C, C, and C.
1118            
1119             The aliases are:
1120            
1121             =over 4
1122            
1123             =item *
1124            
1125             C or C (C)
1126            
1127             =item *
1128            
1129             C or C (C)
1130            
1131             =item *
1132            
1133             C or C (C)
1134            
1135             =back
1136            
1137             =cut
1138            
1139             Win32::Security::ACE::SE_FILE_OBJECT->reflect->addSlot(
1140             dbmAccessMask => Data::BitMask->new(
1141             FILE_READ_DATA => 0x0001, # file & pipe
1142             FILE_LIST_DIRECTORY => 0x0001, # directory
1143            
1144             FILE_WRITE_DATA => 0x0002, # file & pipe
1145             FILE_ADD_FILE => 0x0002, # directory
1146            
1147             FILE_APPEND_DATA => 0x0004, # file
1148             FILE_ADD_SUBDIRECTORY => 0x0004, # directory
1149             FILE_CREATE_PIPE_INSTANCE => 0x0004, # named pipe
1150            
1151             FILE_READ_EA => 0x0008, # file & directory
1152            
1153             FILE_WRITE_EA => 0x0010, # file & directory
1154            
1155             FILE_EXECUTE => 0x0020, # file
1156             FILE_TRAVERSE => 0x0020, # directory
1157            
1158             FILE_DELETE_CHILD => 0x0040, # directory
1159            
1160             FILE_READ_ATTRIBUTES => 0x0080, # all
1161            
1162             FILE_WRITE_ATTRIBUTES => 0x0100, # all
1163            
1164             Win32::Security::ACE::_ObjectType->dbmAccessMask()->get_constants(),
1165             ),
1166             );
1167            
1168             Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->add_constants(
1169             FILE_ALL_ACCESS => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('STANDARD_RIGHTS_REQUIRED SYNCHRONIZE') | 0x3FF,
1170             FILE_GENERIC_READ => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('STANDARD_RIGHTS_READ FILE_READ_DATA FILE_READ_ATTRIBUTES FILE_READ_EA SYNCHRONIZE'),
1171             FILE_GENERIC_WRITE => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('STANDARD_RIGHTS_WRITE FILE_WRITE_DATA FILE_WRITE_ATTRIBUTES FILE_WRITE_EA FILE_APPEND_DATA SYNCHRONIZE'),
1172             FILE_GENERIC_EXECUTE => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('STANDARD_RIGHTS_EXECUTE FILE_READ_ATTRIBUTES FILE_EXECUTE SYNCHRONIZE'),
1173             );
1174            
1175             Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->add_constants(
1176             FULL => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('STANDARD_RIGHTS_ALL FILE_GENERIC_READ FILE_GENERIC_WRITE FILE_GENERIC_EXECUTE FILE_DELETE_CHILD'),
1177             MODIFY => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('FILE_GENERIC_READ FILE_GENERIC_WRITE FILE_GENERIC_EXECUTE DELETE'),
1178             READ => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('FILE_GENERIC_READ FILE_GENERIC_EXECUTE'),
1179             );
1180            
1181             Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->add_constants(
1182             F => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('FULL'),
1183             M => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('MODIFY'),
1184             R => Win32::Security::ACE::SE_FILE_OBJECT->dbmAccessMask()->build_mask('READ'),
1185             );
1186            
1187             =item C
1188            
1189             Win32 constants for Registry Key Rights. The Registry Key Rights are
1190             C, C, C,
1191             C, C, C, C,
1192             C, C, C, C, and
1193             C.
1194            
1195             C support is still under development.
1196            
1197             =cut
1198            
1199             Win32::Security::ACE::SE_REGISTRY_KEY->reflect->addSlot(
1200             dbmAccessMask => Data::BitMask->new(
1201             KEY_QUERY_VALUE => 0x0001,
1202             KEY_SET_VALUE => 0x0002,
1203             KEY_CREATE_SUB_KEY => 0x0004,
1204             KEY_ENUMERATE_SUB_KEYS => 0x0008,
1205             KEY_NOTIFY => 0x0010,
1206             KEY_CREATE_LINK => 0x0020,
1207             KEY_WOW64_64 => 0x0100,
1208             KEY_WOW64_32KEY => 0x0200,
1209            
1210             Win32::Security::ACE::_ObjectType->dbmAccessMask()->get_constants(),
1211             ),
1212             );
1213            
1214             Win32::Security::ACE::SE_REGISTRY_KEY->dbmAccessMask()->add_constants(
1215             KEY_READ => Win32::Security::ACE::SE_REGISTRY_KEY->dbmAccessMask()->build_mask({
1216             STANDARD_RIGHTS_READ => 1,
1217             KEY_QUERY_VALUE => 1,
1218             KEY_ENUMERATE_SUB_KEYS => 1,
1219             KEY_NOTIFY => 1,
1220             SYNCHRONIZE => 0,
1221             }),
1222             KEY_WRITE => Win32::Security::ACE::SE_REGISTRY_KEY->dbmAccessMask()->build_mask({
1223             STANDARD_RIGHTS_WRITE => 1,
1224             KEY_SET_VALUE => 1,
1225             KEY_CREATE_SUB_KEY => 1,
1226             SYNCHRONIZE => 0,
1227             }),
1228             KEY_ALL_ACCESS => Win32::Security::ACE::SE_REGISTRY_KEY->dbmAccessMask()->build_mask({
1229             STANDARD_RIGHTS_ALL => 1,
1230             KEY_QUERY_VALUE => 1,
1231             KEY_SET_VALUE => 1,
1232             KEY_CREATE_SUB_KEY => 1,
1233             KEY_ENUMERATE_SUB_KEYS => 1,
1234             KEY_NOTIFY => 1,
1235             KEY_CREATE_LINK => 1,
1236             SYNCHRONIZE => 0,
1237             }),
1238             );
1239            
1240             Win32::Security::ACE::SE_REGISTRY_KEY->dbmAccessMask()->add_constants(
1241             KEY_EXECUTE => Win32::Security::ACE::SE_REGISTRY_KEY->dbmAccessMask()->build_mask({
1242             KEY_READ => 1,
1243             SYNCHRONIZE => 0,
1244             }),
1245             );
1246            
1247             =back
1248            
1249             =cut
1250            
1251            
1252            
1253             =head2 C
1254            
1255             Returns the integer form of the Access Mask. Useful for equality checks and
1256             bitwise comparisons with other calls to C.
1257            
1258             If called with a passed parameter, mutates the ACE to that new accessMask value.
1259             All forms of accessMask access accept all forms as parameters when used as a
1260             setter.
1261            
1262             =cut
1263            
1264             Win32::Security::ACE::_ObjectType->reflect->addSlot(
1265             rawAccessMask => sub {
1266             my $self = shift;
1267             my $thing = $$self;
1268            
1269             if (scalar(@_)) {
1270             $self->rawAce($self->buildRawAceNamed(accessMask => $_[0]));
1271             return $self;
1272             } else {
1273             exists $thing->{rawAccessMask} or $self->_splitRawAce;
1274             return $thing->{rawAccessMask};
1275             }
1276             },
1277             );
1278            
1279            
1280             =head2 C
1281            
1282             Returns the C form of the Access Mask (i.e. a hash
1283             containing all matching constants for the Access Mask of the ACE).
1284            
1285             If called with a passed parameter, mutates the ACE to that new accessMask value.
1286             All forms of accessMask access accept all forms as parameters when used as a
1287             setter.
1288            
1289             =cut
1290            
1291             Win32::Security::ACE::_ObjectType->reflect->addSlot(
1292             accessMask => sub {
1293             my $self = shift;
1294             my $thing = $$self;
1295            
1296             if (scalar(@_)) {
1297             $self->rawAce($self->buildRawAceNamed(accessMask => $_[0]));
1298             return $self;
1299             } else {
1300             exists $thing->{accessMask} or $thing->{accessMask} = $self->dbmAccessMask()->break_mask($self->rawAccessMask());
1301             return {%{$thing->{accessMask}}};
1302             }
1303             },
1304             );
1305            
1306            
1307             =head2 C
1308            
1309             Returns the C form of the Access Mask (i.e. a hash
1310             containing a set of constants sufficient to recreate and explain the Access Mask
1311             of the ACE).
1312            
1313             If called with a passed parameter, mutates the ACE to that new accessMask value.
1314             All forms of accessMask access accept all forms as parameters when used as a
1315             setter.
1316            
1317             =cut
1318            
1319             Win32::Security::ACE::_ObjectType->reflect->addSlot(
1320             explainAccessMask => sub {
1321             my $self = shift;
1322             my $thing = $$self;
1323            
1324             if (scalar(@_)) {
1325             $self->rawAce($self->buildRawAceNamed(accessMask => $_[0]));
1326             return $self;
1327             } else {
1328             exists $thing->{explainAccessMask} or $thing->{explainAccessMask} = $self->dbmAccessMask()->explain_mask($self->rawAccessMask());
1329             return {%{$thing->{explainAccessMask}}};
1330             }
1331             },
1332             );
1333            
1334            
1335             =head2 C
1336            
1337             This returns an Access Mask cleansed of C permissions for the ACE in
1338             question. Some of the Object Types define special behavior for this.
1339            
1340             =over 4
1341            
1342             =cut
1343            
1344             Win32::Security::ACE::_ObjectType->reflect->addSlot(
1345             cleansedAccessMask => sub {
1346             my $self = shift;
1347             my $thing = $$self;
1348            
1349             return $self->accessMask();
1350             },
1351             );
1352            
1353            
1354             =item C
1355            
1356             Clears the C, C, C, and
1357             C bits and replaces them with the constants C,
1358             C, C, and C respectively. This
1359             is required for correctly interpreting inheritance of some C
1360             ACEs.
1361            
1362             =cut
1363            
1364             Win32::Security::ACE::SE_FILE_OBJECT->reflect->addSlot(
1365             cleansedAccessMask => sub {
1366             my $self = shift;
1367             my $thing = $$self;
1368            
1369             unless (exists $thing->{cleansedAccessMask}) {
1370             my $cleanse_hash = {
1371             GENERIC_READ => ['FILE_GENERIC_READ'],
1372             GENERIC_WRITE => ['FILE_GENERIC_WRITE'],
1373             GENERIC_EXECUTE => ['FILE_GENERIC_EXECUTE'],
1374             GENERIC_ALL => ['FULL'],
1375             };
1376            
1377             my $cleansedAccessMask = $self->accessMask();
1378            
1379             foreach my $i (%$cleanse_hash) {
1380             if ($cleansedAccessMask->{$i}) {
1381             delete $cleansedAccessMask->{$i};
1382             @{$cleansedAccessMask}{@{$cleanse_hash->{$i}}} = (1) x scalar(@{$cleanse_hash->{$i}});
1383             }
1384             }
1385            
1386             $thing->{cleansedAccessMask} = $cleansedAccessMask;
1387             }
1388            
1389             return {%{$thing->{cleansedAccessMask}}};
1390             },
1391             );
1392            
1393             =back
1394            
1395             =cut
1396            
1397             =head1 AUTHOR
1398            
1399             Toby Ovod-Everett, toby@ovod-everett.org
1400            
1401             =cut
1402            
1403             1;