| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Apache::CryptHash; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
#require 5.005_62; |
|
4
|
1
|
|
|
1
|
|
622
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
39
|
|
|
5
|
|
|
|
|
|
|
#use warnings; |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
BEGIN { |
|
8
|
|
|
|
|
|
|
# use Apache; |
|
9
|
1
|
|
|
1
|
|
670
|
use MIME::Base64; |
|
|
1
|
|
|
|
|
711
|
|
|
|
1
|
|
|
|
|
56
|
|
|
10
|
1
|
|
|
1
|
|
1279
|
use Crypt::CapnMidNite; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
use vars qw($VERSION); |
|
12
|
|
|
|
|
|
|
$VERSION = do { my @r = (q$Revision: 3.03 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; |
|
13
|
|
|
|
|
|
|
} |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
sub init() { |
|
17
|
|
|
|
|
|
|
my ($proto, $crypt) = @_; |
|
18
|
|
|
|
|
|
|
my $class = ref($proto) || $proto; |
|
19
|
|
|
|
|
|
|
my $self = {}; |
|
20
|
|
|
|
|
|
|
$self->{NAME} = 'Secret'; # default header name |
|
21
|
|
|
|
|
|
|
$self->{CRYPT} = $crypt || do { # default password is hostname |
|
22
|
|
|
|
|
|
|
require Sys::Hostname; # 'no, NO' turns encryption off |
|
23
|
|
|
|
|
|
|
&Sys::Hostname::hostname; |
|
24
|
|
|
|
|
|
|
}; |
|
25
|
|
|
|
|
|
|
bless ($self, $class); |
|
26
|
|
|
|
|
|
|
return $self; |
|
27
|
|
|
|
|
|
|
} |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub name { |
|
30
|
|
|
|
|
|
|
&_readNset(\shift->{NAME},@_); |
|
31
|
|
|
|
|
|
|
} |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
sub passcode { |
|
34
|
|
|
|
|
|
|
&_readNset(\shift->{CRYPT},@_); |
|
35
|
|
|
|
|
|
|
} |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _readNset { |
|
38
|
|
|
|
|
|
|
my($var,$new) = @_; |
|
39
|
|
|
|
|
|
|
my $rv = $$var; |
|
40
|
|
|
|
|
|
|
$$var = $new if defined $new; |
|
41
|
|
|
|
|
|
|
return $rv; |
|
42
|
|
|
|
|
|
|
} |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
##################################################### |
|
45
|
|
|
|
|
|
|
# md5_hex |
|
46
|
|
|
|
|
|
|
# |
|
47
|
|
|
|
|
|
|
# input: string |
|
48
|
|
|
|
|
|
|
# returns: md5 hex hash of string |
|
49
|
|
|
|
|
|
|
# |
|
50
|
|
|
|
|
|
|
sub md5_hex($$) { |
|
51
|
|
|
|
|
|
|
my ($self, $string) = @_; |
|
52
|
|
|
|
|
|
|
return Crypt::CapnMidNite->new->md5_hex($string); |
|
53
|
|
|
|
|
|
|
} |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
##################################################### |
|
56
|
|
|
|
|
|
|
# md5_b64 |
|
57
|
|
|
|
|
|
|
# |
|
58
|
|
|
|
|
|
|
# input: string |
|
59
|
|
|
|
|
|
|
# returns: md5 base 64 of string |
|
60
|
|
|
|
|
|
|
# |
|
61
|
|
|
|
|
|
|
sub md5_b64($$) { |
|
62
|
|
|
|
|
|
|
my ($self, $string) = @_; |
|
63
|
|
|
|
|
|
|
return Crypt::CapnMidNite->new->md5_base64($string); |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
##################################################### |
|
67
|
|
|
|
|
|
|
# encode |
|
68
|
|
|
|
|
|
|
# create an encrypted cookie from data values passed in hash |
|
69
|
|
|
|
|
|
|
# input: pointer to hash, # \%p |
|
70
|
|
|
|
|
|
|
# (optional) pointer to keys # \@k |
|
71
|
|
|
|
|
|
|
# (array) of values to include in MAC |
|
72
|
|
|
|
|
|
|
# these must be invarient and will |
|
73
|
|
|
|
|
|
|
# fail to decrypt otherwise |
|
74
|
|
|
|
|
|
|
# |
|
75
|
|
|
|
|
|
|
sub encode($$$) { |
|
76
|
|
|
|
|
|
|
my ( $self, $state, $k ) = @_; # get my self |
|
77
|
|
|
|
|
|
|
&_MAC($self, $state, $k, 'generate'); # add MAC to state |
|
78
|
|
|
|
|
|
|
my $cipher = Crypt::CapnMidNite->new_md5_rc4($self->{CRYPT}); |
|
79
|
|
|
|
|
|
|
my %s = %$state; |
|
80
|
|
|
|
|
|
|
foreach (keys %s) { |
|
81
|
|
|
|
|
|
|
$s{$_} =~ s/:/%58/g; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
|
|
|
|
|
|
my $cook = $self->{NAME}; |
|
84
|
|
|
|
|
|
|
if ( $self->{CRYPT} =~ /^no$/i ) { |
|
85
|
|
|
|
|
|
|
$cook .= '.Debug:' . join ':', %s; |
|
86
|
|
|
|
|
|
|
} else { |
|
87
|
|
|
|
|
|
|
$cook .= ':' . MIME::Base64::encode($cipher->encrypt(join ':', %s),""); |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
$cook =~ tr/=/$/; |
|
90
|
|
|
|
|
|
|
return $cook; |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
##################################### |
|
94
|
|
|
|
|
|
|
# |
|
95
|
|
|
|
|
|
|
# input: pointer to cookie value # \$string |
|
96
|
|
|
|
|
|
|
# pointer to state hash # \%state to fill |
|
97
|
|
|
|
|
|
|
# pointer key arrau in MAC # \@keys |
|
98
|
|
|
|
|
|
|
# return: true or undef, fill hash with state values if true |
|
99
|
|
|
|
|
|
|
# |
|
100
|
|
|
|
|
|
|
sub decode ($$$) { |
|
101
|
|
|
|
|
|
|
my ($self, $cook, $state, $ck) = @_; |
|
102
|
|
|
|
|
|
|
my %s; |
|
103
|
|
|
|
|
|
|
$$cook =~ tr/$/=/; |
|
104
|
|
|
|
|
|
|
my $rv = &_decrypt($self, $cook, \%s, $ck); |
|
105
|
|
|
|
|
|
|
return undef unless $rv; |
|
106
|
|
|
|
|
|
|
%$state = %s; |
|
107
|
|
|
|
|
|
|
$rv; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub _decrypt { |
|
111
|
|
|
|
|
|
|
my ($self, $cook, $state, $ck) = @_; |
|
112
|
|
|
|
|
|
|
my $cipher = Crypt::CapnMidNite->new_md5_rc4($self->{CRYPT}); |
|
113
|
|
|
|
|
|
|
my ($flag, $realcook) = split(':', $$cook, 2); |
|
114
|
|
|
|
|
|
|
$realcook =~ tr/$/=/; |
|
115
|
|
|
|
|
|
|
if ( $flag =~ /.Debug$/ ) { |
|
116
|
|
|
|
|
|
|
%$state = &_evensplit(':', $realcook); |
|
117
|
|
|
|
|
|
|
} else { |
|
118
|
|
|
|
|
|
|
%$state = &_evensplit(':',$cipher->decrypt(MIME::Base64::decode($realcook))); |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
return undef unless exists ${$state}{MAC}; # punt if decode failure |
|
121
|
|
|
|
|
|
|
foreach (keys %$state) { |
|
122
|
|
|
|
|
|
|
${$state}{$_} =~ s/%58/:/g; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
# invalid if the cookie was tampered with |
|
125
|
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
return undef unless &_MAC($self, $state, $ck, 'check'); |
|
127
|
|
|
|
|
|
|
foreach ( @$ck ) { |
|
128
|
|
|
|
|
|
|
return undef unless exists ${$state}{$_}; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
$flag; # return true |
|
131
|
|
|
|
|
|
|
} |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub checkMAC { |
|
134
|
|
|
|
|
|
|
my ( $self, $s, $k ) = @_; |
|
135
|
|
|
|
|
|
|
return _MAC($self, $s, $k, 'check'); |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub _MAC { |
|
139
|
|
|
|
|
|
|
my ( $self, $s, $k, $action ) = @_; |
|
140
|
|
|
|
|
|
|
@_ = ($k) ? sort @$k : (); |
|
141
|
|
|
|
|
|
|
my @fields = @{$s}{@_}; |
|
142
|
|
|
|
|
|
|
my $md5 = Crypt::CapnMidNite->new_md5; |
|
143
|
|
|
|
|
|
|
my $newmac = $md5->md5_base64($self->{CRYPT} . |
|
144
|
|
|
|
|
|
|
$md5->md5_base64(join '', $self->{CRYPT}, @fields)); |
|
145
|
|
|
|
|
|
|
return $s->{MAC} = $newmac if $action eq 'generate'; |
|
146
|
|
|
|
|
|
|
return 1 if ($newmac eq $s->{MAC} && $action eq 'check'); |
|
147
|
|
|
|
|
|
|
return undef; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
# split to an even number of fields |
|
151
|
|
|
|
|
|
|
# this will split to a hash when the trailing value is null |
|
152
|
|
|
|
|
|
|
# |
|
153
|
|
|
|
|
|
|
sub _evensplit { |
|
154
|
|
|
|
|
|
|
my ( $m, $s ) = @_; |
|
155
|
|
|
|
|
|
|
@_ = split(/$m/, $s, -1); |
|
156
|
|
|
|
|
|
|
push ( @_, '') if @_ % 2; |
|
157
|
|
|
|
|
|
|
@_; |
|
158
|
|
|
|
|
|
|
} |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
1; |
|
161
|
|
|
|
|
|
|
__END__ |