File Coverage

blib/lib/Parse/Win32Registry/WinNT/Security.pm
Criterion Covered Total %
statement 76 85 89.4
branch 17 24 70.8
condition n/a
subroutine 11 14 78.5
pod 0 7 0.0
total 104 130 80.0


line stmt bran cond sub pod time code
1             package Parse::Win32Registry::WinNT::Security;
2              
3 13     13   96 use strict;
  13         28  
  13         403  
4 13     13   67 use warnings;
  13         29  
  13         364  
5              
6 13     13   68 use base qw(Parse::Win32Registry::Entry);
  13         27  
  13         1245  
7              
8 13     13   87 use Carp;
  13         29  
  13         824  
9 13     13   90 use Parse::Win32Registry::Base qw(:all);
  13         35  
  13         2855  
10              
11 13     13   97 use constant SK_HEADER_LENGTH => 0x18;
  13         29  
  13         1060  
12 13     13   102 use constant OFFSET_TO_FIRST_HBIN => 0x1000;
  13         26  
  13         8635  
13              
14             sub new {
15 14     14 0 390 my $class = shift;
16 14         28 my $regfile = shift;
17 14         29 my $offset = shift; # offset to sk record relative to start of file
18              
19 14 50       42 croak 'Missing registry file' if !defined $regfile;
20 14 50       34 croak 'Missing offset' if !defined $offset;
21              
22 14 50       53 if (defined(my $cache = $regfile->{_security_cache})) {
23 14 100       44 if (exists $cache->{$offset}) {
24 2         10 return $cache->{$offset};
25             }
26             }
27              
28 12         58 my $fh = $regfile->get_filehandle;
29              
30             # 0x00 dword = security length (negative = allocated)
31             # 0x04 word = 'sk' signature
32             # 0x08 dword = offset to previous sk
33             # 0x0c dword = offset to next sk
34             # 0x10 dword = ref count
35             # 0x14 dword = length of security descriptor
36             # 0x18 = start of security descriptor
37              
38             # Extracted offsets are always relative to first hbin
39              
40 12         88 sysseek($fh, $offset, 0);
41 12         120 my $bytes_read = sysread($fh, my $sk_header, SK_HEADER_LENGTH);
42 12 100       47 if ($bytes_read != SK_HEADER_LENGTH) {
43 1         5 warnf('Could not read security at 0x%x', $offset);
44 1         15 return;
45             }
46              
47 11         72 my ($length,
48             $sig,
49             $offset_to_previous,
50             $offset_to_next,
51             $ref_count,
52             $sd_length,
53             ) = unpack('Va2x2VVVV', $sk_header);
54              
55 11 50       39 $offset_to_previous += OFFSET_TO_FIRST_HBIN
56             if $offset_to_previous != 0xffffffff;
57 11 50       27 $offset_to_next += OFFSET_TO_FIRST_HBIN
58             if $offset_to_next != 0xffffffff;
59              
60 11         18 my $allocated = 0;
61 11 50       30 if ($length > 0x7fffffff) {
62 11         19 $allocated = 1;
63 11         22 $length = (0xffffffff - $length) + 1;
64             }
65             # allocated should be true
66              
67 11 100       35 if ($sig ne 'sk') {
68 1         6 warnf('Invalid signature for security at 0x%x', $offset);
69 1         17 return;
70             }
71              
72 10         90 $bytes_read = sysread($fh, my $sd_data, $sd_length);
73 10 100       40 if ($bytes_read != $sd_length) {
74 1         6 warnf('Could not read security descriptor for security at 0x%x',
75             $offset);
76 1         17 return;
77             }
78              
79 9         39 my $sd = unpack_security_descriptor($sd_data);
80 9 100       26 if (!defined $sd) {
81 1         4 warnf('Invalid security descriptor for security at 0x%x',
82             $offset);
83             # Abandon security object if security descriptor is invalid
84 1         24 return;
85             }
86              
87 8         16 my $self = {};
88 8         17 $self->{_regfile} = $regfile;
89 8         33 $self->{_offset} = $offset;
90 8         16 $self->{_length} = $length;
91 8         17 $self->{_allocated} = $allocated;
92 8         27 $self->{_tag} = $sig;
93 8         17 $self->{_offset_to_previous} = $offset_to_previous;
94 8         16 $self->{_offset_to_next} = $offset_to_next;
95 8         31 $self->{_ref_count} = $ref_count;
96 8         17 $self->{_security_descriptor_length} = $sd_length;
97 8         14 $self->{_security_descriptor} = $sd;
98 8         17 bless $self, $class;
99              
100 8 50       21 if (defined(my $cache = $regfile->{_security_cache})) {
101 8         22 $cache->{$offset} = $self;
102             }
103              
104 8         41 return $self;
105             }
106              
107             sub get_previous {
108 0     0 0 0 my $self = shift;
109 0         0 my $regfile = $self->{_regfile};
110 0         0 my $offset_to_previous = $self->{_offset_to_previous};
111              
112 0         0 return Parse::Win32Registry::WinNT::Security->new($regfile,
113             $offset_to_previous);
114             }
115              
116             sub get_next {
117 7     7 0 19 my $self = shift;
118 7         18 my $regfile = $self->{_regfile};
119 7         14 my $offset_to_next = $self->{_offset_to_next};
120              
121 7         22 return Parse::Win32Registry::WinNT::Security->new($regfile,
122             $offset_to_next);
123             }
124              
125             sub get_reference_count {
126 0     0 0 0 my $self = shift;
127              
128 0         0 return $self->{_ref_count};
129             }
130              
131             sub get_security_descriptor {
132 7     7 0 15 my $self = shift;
133              
134 7         32 return $self->{_security_descriptor};
135             }
136              
137             sub as_string {
138 2     2 0 7 my $self = shift;
139              
140 2         10 return '(security entry)';
141             }
142              
143             sub parse_info {
144 0     0 0   my $self = shift;
145              
146             my $info = sprintf '0x%x sk len=0x%x alloc=%d prev=0x%x,next=0x%x refs=%d',
147             $self->{_offset},
148             $self->{_length},
149             $self->{_allocated},
150             $self->{_offset_to_previous},
151             $self->{_offset_to_next},
152 0           $self->{_ref_count};
153              
154 0           return $info;
155             }
156              
157             1;