Lines 31-42
Koha::Token - Tokenizer
Link Here
|
31 |
|
31 |
|
32 |
# safely generate a CSRF token (nonblocking) |
32 |
# safely generate a CSRF token (nonblocking) |
33 |
my $csrf_token = $tokenizer->generate({ |
33 |
my $csrf_token = $tokenizer->generate({ |
34 |
CSRF => 1, id => $id, secret => $secret, |
34 |
type => 'CSRF', id => $id, secret => $secret, |
35 |
}); |
35 |
}); |
36 |
|
36 |
|
37 |
# or check a CSRF token |
37 |
# or check a CSRF token |
38 |
my $result = $tokenizer->check({ |
38 |
my $result = $tokenizer->check_csrf({ |
39 |
CSRF => 1, id => $id, secret => $secret, token => $token, |
39 |
id => $id, secret => $secret, token => $token, |
40 |
}); |
40 |
}); |
41 |
|
41 |
|
42 |
=head1 DESCRIPTION |
42 |
=head1 DESCRIPTION |
Lines 48-53
Koha::Token - Tokenizer
Link Here
|
48 |
=cut |
48 |
=cut |
49 |
|
49 |
|
50 |
use Modern::Perl; |
50 |
use Modern::Perl; |
|
|
51 |
use Bytes::Random::Secure (); |
52 |
use String::Random (); |
53 |
use WWW::CSRF (); |
51 |
use base qw(Class::Accessor); |
54 |
use base qw(Class::Accessor); |
52 |
use constant HMAC_SHA1_LENGTH => 20; |
55 |
use constant HMAC_SHA1_LENGTH => 20; |
53 |
|
56 |
|
Lines 68-74
sub new {
Link Here
|
68 |
|
71 |
|
69 |
my $token = $tokenizer->generate({ length => 20 }); |
72 |
my $token = $tokenizer->generate({ length => 20 }); |
70 |
my $csrf_token = $tokenizer->generate({ |
73 |
my $csrf_token = $tokenizer->generate({ |
71 |
CSRF => 1, id => $id, secret => $secret, |
74 |
type => 'CSRF', id => $id, secret => $secret, |
72 |
}); |
75 |
}); |
73 |
|
76 |
|
74 |
Generate several types of tokens. Now includes CSRF. |
77 |
Generate several types of tokens. Now includes CSRF. |
Lines 78-84
sub new {
Link Here
|
78 |
|
81 |
|
79 |
sub generate { |
82 |
sub generate { |
80 |
my ( $self, $params ) = @_; |
83 |
my ( $self, $params ) = @_; |
81 |
if( $params->{CSRF} ) { |
84 |
if( $params->{type} && $params->{type} eq 'CSRF' ) { |
82 |
$self->{lasttoken} = _gen_csrf( $params ); |
85 |
$self->{lasttoken} = _gen_csrf( $params ); |
83 |
} else { |
86 |
} else { |
84 |
$self->{lasttoken} = _gen_rand( $params ); |
87 |
$self->{lasttoken} = _gen_rand( $params ); |
Lines 86-95
sub generate {
Link Here
|
86 |
return $self->{lasttoken}; |
89 |
return $self->{lasttoken}; |
87 |
} |
90 |
} |
88 |
|
91 |
|
|
|
92 |
=head2 generate_csrf |
93 |
|
94 |
Shortcut for: generate({ type => 'CSRF', ... }) |
95 |
|
96 |
=cut |
97 |
|
98 |
sub generate_csrf { |
99 |
my ( $self, $params ) = @_; |
100 |
return $self->generate({ %$params, type => 'CSRF' }); |
101 |
} |
102 |
|
89 |
=head2 check |
103 |
=head2 check |
90 |
|
104 |
|
91 |
my $result = $tokenizer->check({ |
105 |
my $result = $tokenizer->check({ |
92 |
CSRF => 1, id => $id, secret => $secret, token => $token, |
106 |
type => 'CSRF', id => $id, secret => $secret, token => $token, |
93 |
}); |
107 |
}); |
94 |
|
108 |
|
95 |
Check several types of tokens. Now includes CSRF. |
109 |
Check several types of tokens. Now includes CSRF. |
Lines 99-110
sub generate {
Link Here
|
99 |
|
113 |
|
100 |
sub check { |
114 |
sub check { |
101 |
my ( $self, $params ) = @_; |
115 |
my ( $self, $params ) = @_; |
102 |
if( $params->{CSRF} ) { |
116 |
if( $params->{type} && $params->{type} eq 'CSRF' ) { |
103 |
return _chk_csrf( $params ); |
117 |
return _chk_csrf( $params ); |
104 |
} |
118 |
} |
105 |
return; |
119 |
return; |
106 |
} |
120 |
} |
107 |
|
121 |
|
|
|
122 |
=head2 check_csrf |
123 |
|
124 |
Shortcut for: check({ type => 'CSRF', ... }) |
125 |
|
126 |
=cut |
127 |
|
128 |
sub check_csrf { |
129 |
my ( $self, $params ) = @_; |
130 |
return $self->check({ %$params, type => 'CSRF' }); |
131 |
} |
132 |
|
108 |
# --- Internal routines --- |
133 |
# --- Internal routines --- |
109 |
|
134 |
|
110 |
sub _gen_csrf { |
135 |
sub _gen_csrf { |
Lines 116-123
sub _gen_csrf {
Link Here
|
116 |
my ( $params ) = @_; |
141 |
my ( $params ) = @_; |
117 |
return if !$params->{id} || !$params->{secret}; |
142 |
return if !$params->{id} || !$params->{secret}; |
118 |
|
143 |
|
119 |
require Bytes::Random::Secure; |
|
|
120 |
require WWW::CSRF; |
121 |
|
144 |
|
122 |
my $randomizer = Bytes::Random::Secure->new( NonBlocking => 1 ); |
145 |
my $randomizer = Bytes::Random::Secure->new( NonBlocking => 1 ); |
123 |
# this is most fundamental: do not use /dev/random since it is |
146 |
# this is most fundamental: do not use /dev/random since it is |
Lines 134-140
sub _chk_csrf {
Link Here
|
134 |
my ( $params ) = @_; |
157 |
my ( $params ) = @_; |
135 |
return if !$params->{id} || !$params->{secret} || !$params->{token}; |
158 |
return if !$params->{id} || !$params->{secret} || !$params->{token}; |
136 |
|
159 |
|
137 |
require WWW::CSRF; |
|
|
138 |
my $csrf_status = WWW::CSRF::check_csrf_token( |
160 |
my $csrf_status = WWW::CSRF::check_csrf_token( |
139 |
$params->{id}, |
161 |
$params->{id}, |
140 |
$params->{secret}, |
162 |
$params->{secret}, |
Lines 148-154
sub _gen_rand {
Link Here
|
148 |
my $length = $params->{length} || 1; |
170 |
my $length = $params->{length} || 1; |
149 |
$length = 1 unless $length > 0; |
171 |
$length = 1 unless $length > 0; |
150 |
|
172 |
|
151 |
require String::Random; |
|
|
152 |
return String::Random::random_string( '.' x $length ); |
173 |
return String::Random::random_string( '.' x $length ); |
153 |
} |
174 |
} |
154 |
|
175 |
|