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
|
|
|
|
|
|
|
|