| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package OpenID::Lite::Realm; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
2886
|
use Any::Moose; |
|
|
2
|
|
|
|
|
44714
|
|
|
|
2
|
|
|
|
|
17
|
|
|
4
|
2
|
|
|
2
|
|
2067
|
use URI; |
|
|
2
|
|
|
|
|
8282
|
|
|
|
2
|
|
|
|
|
63
|
|
|
5
|
2
|
|
|
2
|
|
1065
|
use List::MoreUtils qw(any none); |
|
|
2
|
|
|
|
|
1277
|
|
|
|
2
|
|
|
|
|
142
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
2
|
|
|
2
|
|
1039
|
use OpenID::Lite::Provider::Discover; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use OpenID::Lite::Util::URI; |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
has 'origin' => ( |
|
11
|
|
|
|
|
|
|
is => 'ro', |
|
12
|
|
|
|
|
|
|
isa => 'Str', |
|
13
|
|
|
|
|
|
|
required => 1, |
|
14
|
|
|
|
|
|
|
); |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
has 'scheme' => ( |
|
17
|
|
|
|
|
|
|
is => 'ro', |
|
18
|
|
|
|
|
|
|
isa => 'Str', |
|
19
|
|
|
|
|
|
|
required => 1, |
|
20
|
|
|
|
|
|
|
); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has 'host' => ( |
|
23
|
|
|
|
|
|
|
is => 'ro', |
|
24
|
|
|
|
|
|
|
isa => 'Str', |
|
25
|
|
|
|
|
|
|
default => '', |
|
26
|
|
|
|
|
|
|
); |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
has 'port' => ( |
|
29
|
|
|
|
|
|
|
is => 'ro', |
|
30
|
|
|
|
|
|
|
isa => 'Int', |
|
31
|
|
|
|
|
|
|
); |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
has 'path' => ( |
|
34
|
|
|
|
|
|
|
is => 'ro', |
|
35
|
|
|
|
|
|
|
isa => 'Str', |
|
36
|
|
|
|
|
|
|
default => '/', |
|
37
|
|
|
|
|
|
|
); |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
has 'has_wildcard' => ( |
|
40
|
|
|
|
|
|
|
is => 'ro', |
|
41
|
|
|
|
|
|
|
isa => 'Bool', |
|
42
|
|
|
|
|
|
|
default => 0, |
|
43
|
|
|
|
|
|
|
); |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
my @TLDs = qw( |
|
46
|
|
|
|
|
|
|
ac ad ae aero af ag ai al am an ao aq ar arpa as asia at |
|
47
|
|
|
|
|
|
|
au aw ax az ba bb bd be bf bg bh bi biz bj bm bn bo br bs bt |
|
48
|
|
|
|
|
|
|
bv bw by bz ca cat cc cd cf cg ch ci ck cl cm cn co com coop |
|
49
|
|
|
|
|
|
|
cr cu cv cx cy cz de dj dk dm do dz ec edu ee eg er es et eu |
|
50
|
|
|
|
|
|
|
fi fj fk fm fo fr ga gb gd ge gf gg gh gi gl gm gn gov gp gq |
|
51
|
|
|
|
|
|
|
gr gs gt gu gw gy hk hm hn hr ht hu id ie il im in info int |
|
52
|
|
|
|
|
|
|
io iq ir is it je jm jo jobs jp ke kg kh ki km kn kp kr kw |
|
53
|
|
|
|
|
|
|
ky kz la lb lc li lk lr ls lt lu lv ly ma mc md me mg mh mil |
|
54
|
|
|
|
|
|
|
mk ml mm mn mo mobi mp mq mr ms mt mu museum mv mw mx my mz |
|
55
|
|
|
|
|
|
|
na name nc ne net nf ng ni nl no np nr nu nz om org pa pe pf |
|
56
|
|
|
|
|
|
|
pg ph pk pl pm pn pr pro ps pt pw py qa re ro rs ru rw sa sb |
|
57
|
|
|
|
|
|
|
sc sd se sg sh si sj sk sl sm sn so sr st su sv sy sz tc td |
|
58
|
|
|
|
|
|
|
tel tf tg th tj tk tl tm tn to tp tr travel tt tv tw tz ua |
|
59
|
|
|
|
|
|
|
ug uk us uy uz va vc ve vg vi vn vu wf ws xn--0zwm56d |
|
60
|
|
|
|
|
|
|
xn--11b5bs3a9aj6g xn--80akhbyknj4f xn--9t4b11yi5a |
|
61
|
|
|
|
|
|
|
xn--deba0ad xn--g6w251d xn--hgbk6aj7f53bba |
|
62
|
|
|
|
|
|
|
xn--hlcj6aya9esc7a xn--jxalpdlp xn--kgbechtv xn--zckzah ye |
|
63
|
|
|
|
|
|
|
yt yu za zm zw |
|
64
|
|
|
|
|
|
|
); |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub return_to_matches { |
|
67
|
|
|
|
|
|
|
my ( $class, $urls, $return_to ) = @_; |
|
68
|
|
|
|
|
|
|
$return_to ||= ''; |
|
69
|
|
|
|
|
|
|
for my $url (@$urls) { |
|
70
|
|
|
|
|
|
|
my $r = $class->parse($url); |
|
71
|
|
|
|
|
|
|
return 1 |
|
72
|
|
|
|
|
|
|
if ( $r |
|
73
|
|
|
|
|
|
|
&& !$r->has_wildcard |
|
74
|
|
|
|
|
|
|
&& $r->validate_url($return_to) ); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
return 0; |
|
77
|
|
|
|
|
|
|
} |
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub get_allowed_return_urls { |
|
80
|
|
|
|
|
|
|
my ( $self, $url ) = @_; |
|
81
|
|
|
|
|
|
|
my $disco = OpenID::Lite::Provider::Discover->new(); |
|
82
|
|
|
|
|
|
|
my $urls = $disco->discover($url, 1) |
|
83
|
|
|
|
|
|
|
or return; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub verify_return_to { |
|
87
|
|
|
|
|
|
|
my ( $class, $realm, $return_to ) = @_; |
|
88
|
|
|
|
|
|
|
my $r = $class->parse($realm); |
|
89
|
|
|
|
|
|
|
return unless $r; |
|
90
|
|
|
|
|
|
|
my $disco_url = $r->build_discovery_url(); |
|
91
|
|
|
|
|
|
|
my $allowable_urls = $class->get_allowed_return_urls($disco_url); |
|
92
|
|
|
|
|
|
|
if ( $class->return_to_matches( $allowable_urls, $return_to ) ) { |
|
93
|
|
|
|
|
|
|
return 1; |
|
94
|
|
|
|
|
|
|
} |
|
95
|
|
|
|
|
|
|
return 0; |
|
96
|
|
|
|
|
|
|
} |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub parse { |
|
99
|
|
|
|
|
|
|
my ( $class, $realm ) = @_; |
|
100
|
|
|
|
|
|
|
my $origin = $realm; |
|
101
|
|
|
|
|
|
|
my $found_wildcard = ( index( $realm, q{://*.} ) >= 0 ) ? 1 : 0; |
|
102
|
|
|
|
|
|
|
$realm =~ s/\*\.// if $found_wildcard; |
|
103
|
|
|
|
|
|
|
if ( !$found_wildcard && $realm =~ m|^https?\://\*/$| ) { |
|
104
|
|
|
|
|
|
|
my $scheme = ( split( /\:/, $realm ) )[0]; |
|
105
|
|
|
|
|
|
|
my $port = $scheme eq 'http' ? 80 : 443; |
|
106
|
|
|
|
|
|
|
return $class->new( |
|
107
|
|
|
|
|
|
|
origin => $origin, |
|
108
|
|
|
|
|
|
|
scheme => $scheme, |
|
109
|
|
|
|
|
|
|
host => '', |
|
110
|
|
|
|
|
|
|
port => $port, |
|
111
|
|
|
|
|
|
|
has_wildcard => 1, |
|
112
|
|
|
|
|
|
|
path => '/', |
|
113
|
|
|
|
|
|
|
); |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
my $parts = $class->_parse($realm); |
|
116
|
|
|
|
|
|
|
return unless $parts; |
|
117
|
|
|
|
|
|
|
my ( $scheme, $host, $port, $path ) = @$parts; |
|
118
|
|
|
|
|
|
|
if ( $path && index( $path, q{#} ) >= 0 ) { |
|
119
|
|
|
|
|
|
|
return; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
return if ( none { $_ eq $scheme } qw(http https) ); |
|
122
|
|
|
|
|
|
|
return $class->new( |
|
123
|
|
|
|
|
|
|
origin => $origin, |
|
124
|
|
|
|
|
|
|
scheme => $scheme, |
|
125
|
|
|
|
|
|
|
host => $host, |
|
126
|
|
|
|
|
|
|
port => $port, |
|
127
|
|
|
|
|
|
|
path => $path, |
|
128
|
|
|
|
|
|
|
has_wildcard => $found_wildcard, |
|
129
|
|
|
|
|
|
|
); |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub _parse { |
|
133
|
|
|
|
|
|
|
my ( $class, $url ) = @_; |
|
134
|
|
|
|
|
|
|
$url = OpenID::Lite::Util::URI->normalize($url) |
|
135
|
|
|
|
|
|
|
or return; |
|
136
|
|
|
|
|
|
|
return unless OpenID::Lite::Util::URI->is_uri($url); |
|
137
|
|
|
|
|
|
|
my $u = URI->new($url); |
|
138
|
|
|
|
|
|
|
my $path = $u->path; |
|
139
|
|
|
|
|
|
|
$path .= sprintf q{?%s}, $u->query if $u->query; |
|
140
|
|
|
|
|
|
|
$path .= sprintf q{#%s}, $u->fragment if $u->fragment; |
|
141
|
|
|
|
|
|
|
return [ $u->scheme || '', $u->host || '', $u->port || '', $path ]; |
|
142
|
|
|
|
|
|
|
} |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
sub check_url { |
|
145
|
|
|
|
|
|
|
my ( $class, $realm, $url ) = @_; |
|
146
|
|
|
|
|
|
|
my $r = $class->parse($realm); |
|
147
|
|
|
|
|
|
|
return ( $r && $r->validate_url($url) ) ? 1 : 0; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
sub check_sanity { |
|
151
|
|
|
|
|
|
|
my ( $class, $realm ) = @_; |
|
152
|
|
|
|
|
|
|
my $r = $class->parse($realm); |
|
153
|
|
|
|
|
|
|
return ( $r && $r->is_sane() ) ? 1 : 0; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub build_discovery_url { |
|
157
|
|
|
|
|
|
|
my $self = shift; |
|
158
|
|
|
|
|
|
|
if ( $self->has_wildcard ) { |
|
159
|
|
|
|
|
|
|
my $port |
|
160
|
|
|
|
|
|
|
= ( $self->port && $self->port != 80 && $self->port != 443 ) |
|
161
|
|
|
|
|
|
|
? sprintf(":%d", $self->port) |
|
162
|
|
|
|
|
|
|
: ''; |
|
163
|
|
|
|
|
|
|
return sprintf q{%s://www.%s%s%s}, |
|
164
|
|
|
|
|
|
|
$self->scheme, |
|
165
|
|
|
|
|
|
|
$self->host, |
|
166
|
|
|
|
|
|
|
$port, |
|
167
|
|
|
|
|
|
|
$self->path; |
|
168
|
|
|
|
|
|
|
} |
|
169
|
|
|
|
|
|
|
else { |
|
170
|
|
|
|
|
|
|
return $self->origin; |
|
171
|
|
|
|
|
|
|
} |
|
172
|
|
|
|
|
|
|
} |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub is_sane { |
|
175
|
|
|
|
|
|
|
my $self = shift; |
|
176
|
|
|
|
|
|
|
return 1 if $self->host eq 'localhost'; |
|
177
|
|
|
|
|
|
|
my @host_parts = split( /\./, $self->host ); |
|
178
|
|
|
|
|
|
|
return 0 if scalar(@host_parts) == 0; |
|
179
|
|
|
|
|
|
|
return 0 if ( any { $_ eq '' } @host_parts ); |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
my $tld = $host_parts[-1]; |
|
182
|
|
|
|
|
|
|
return 0 if ( none { $tld eq $_ } @TLDs ); |
|
183
|
|
|
|
|
|
|
return 0 if scalar(@host_parts) == 1; |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
if ( $self->has_wildcard ) { |
|
186
|
|
|
|
|
|
|
if ( length($tld) == 2 && length( $host_parts[-2] ) <= 3 ) { |
|
187
|
|
|
|
|
|
|
return @host_parts > 2 ? 1 : 0; |
|
188
|
|
|
|
|
|
|
} |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
return 1; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
sub validate_url { |
|
195
|
|
|
|
|
|
|
my ( $self, $url ) = @_; |
|
196
|
|
|
|
|
|
|
my $parts = ref($self)->_parse($url) |
|
197
|
|
|
|
|
|
|
or return 0; |
|
198
|
|
|
|
|
|
|
my ( $scheme, $host, $port, $path ) = @$parts; |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
return 0 unless $self->scheme eq $scheme; |
|
201
|
|
|
|
|
|
|
return 0 unless $self->port == $port; |
|
202
|
|
|
|
|
|
|
return 0 if ( index( $host, q{*} ) >= 0 ); |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
my $s_host = $self->host; |
|
205
|
|
|
|
|
|
|
if ( !$self->has_wildcard ) { |
|
206
|
|
|
|
|
|
|
return 0 if $s_host ne $host; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
elsif ($s_host ne '' |
|
209
|
|
|
|
|
|
|
&& $host !~ /\.$s_host$/ |
|
210
|
|
|
|
|
|
|
&& $host ne $s_host ) |
|
211
|
|
|
|
|
|
|
{ |
|
212
|
|
|
|
|
|
|
return 0; |
|
213
|
|
|
|
|
|
|
} |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
if ( $path ne $self->path ) { |
|
216
|
|
|
|
|
|
|
my $path_length = length( $self->path ); |
|
217
|
|
|
|
|
|
|
my $prefix = substr( $path, 0, $path_length ); |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
return 0 if $self->path ne $prefix; |
|
220
|
|
|
|
|
|
|
my $allowed = ( index( $self->path, q{?} ) >= 0 ) ? q{&} : q{?/}; |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
return ( |
|
223
|
|
|
|
|
|
|
index( $allowed, substr( $self->path, -1 ) ) >= 0 |
|
224
|
|
|
|
|
|
|
|| index( $allowed, substr( $path, $path_length, 1 ) ) >= 0 |
|
225
|
|
|
|
|
|
|
) ? 1 : 0; |
|
226
|
|
|
|
|
|
|
} |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
return 1; |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
no Any::Moose; |
|
232
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
|
233
|
|
|
|
|
|
|
1; |
|
234
|
|
|
|
|
|
|
|