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