View | Details | Raw Unified | Return to bug 18124
Collapse All | Expand All

(-)a/Koha/Token.pm (-7 / +13 lines)
Lines 51-56 use Modern::Perl; Link Here
51
use Bytes::Random::Secure ();
51
use Bytes::Random::Secure ();
52
use String::Random ();
52
use String::Random ();
53
use WWW::CSRF ();
53
use WWW::CSRF ();
54
use Digest::MD5 qw(md5_base64);
55
use Encode qw( encode );
54
use base qw(Class::Accessor);
56
use base qw(Class::Accessor);
55
use constant HMAC_SHA1_LENGTH => 20;
57
use constant HMAC_SHA1_LENGTH => 20;
56
use constant CSRF_EXPIRY_HOURS => 8; # 8 hours instead of 7 days..
58
use constant CSRF_EXPIRY_HOURS => 8; # 8 hours instead of 7 days..
Lines 72-78 sub new { Link Here
72
74
73
    my $token = $tokenizer->generate({ length => 20 });
75
    my $token = $tokenizer->generate({ length => 20 });
74
    my $csrf_token = $tokenizer->generate({
76
    my $csrf_token = $tokenizer->generate({
75
        type => 'CSRF', id => $id, secret => $secret,
77
        type => 'CSRF', id => $id,
76
    });
78
    });
77
79
78
    Generate several types of tokens. Now includes CSRF.
80
    Generate several types of tokens. Now includes CSRF.
Lines 83-89 sub new { Link Here
83
sub generate {
85
sub generate {
84
    my ( $self, $params ) = @_;
86
    my ( $self, $params ) = @_;
85
    if( $params->{type} && $params->{type} eq 'CSRF' ) {
87
    if( $params->{type} && $params->{type} eq 'CSRF' ) {
86
        $self->{lasttoken} = _gen_csrf( $params );
88
        $self->{lasttoken} = _gen_csrf( {
89
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} . $params->{id} ),
90
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
91
        });
87
    } else {
92
    } else {
88
        $self->{lasttoken} = _gen_rand( $params );
93
        $self->{lasttoken} = _gen_rand( $params );
89
    }
94
    }
Lines 98-110 sub generate { Link Here
98
103
99
sub generate_csrf {
104
sub generate_csrf {
100
    my ( $self, $params ) = @_;
105
    my ( $self, $params ) = @_;
106
    return unless $params->{id};
101
    return $self->generate({ %$params, type => 'CSRF' });
107
    return $self->generate({ %$params, type => 'CSRF' });
102
}
108
}
103
109
104
=head2 check
110
=head2 check
105
111
106
    my $result = $tokenizer->check({
112
    my $result = $tokenizer->check({
107
        type => 'CSRF', id => $id, secret => $secret, token => $token,
113
        type => 'CSRF', id => $id, token => $token,
108
    });
114
    });
109
115
110
    Check several types of tokens. Now includes CSRF.
116
    Check several types of tokens. Now includes CSRF.
Lines 156-167 sub _gen_csrf { Link Here
156
162
157
sub _chk_csrf {
163
sub _chk_csrf {
158
    my ( $params ) = @_;
164
    my ( $params ) = @_;
159
    return if !$params->{id} || !$params->{secret} || !$params->{token};
165
    return if !$params->{id} || !$params->{token};
160
166
167
    my $id = Encode::encode( 'UTF-8', C4::Context->userenv->{id} . $params->{id} );
168
    my $secret = md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) );
161
    my $csrf_status = WWW::CSRF::check_csrf_token(
169
    my $csrf_status = WWW::CSRF::check_csrf_token(
162
        $params->{id},
170
        $id, $secret, $params->{token},
163
        $params->{secret},
164
        $params->{token},
165
        { MaxAge => $params->{MaxAge} // ( CSRF_EXPIRY_HOURS * 3600 ) },
171
        { MaxAge => $params->{MaxAge} // ( CSRF_EXPIRY_HOURS * 3600 ) },
166
    );
172
    );
167
    return $csrf_status == WWW::CSRF::CSRF_OK();
173
    return $csrf_status == WWW::CSRF::CSRF_OK();
(-)a/basket/sendbasket.pl (-8 / +2 lines)
Lines 20-26 use Modern::Perl; Link Here
20
use CGI qw ( -utf8 );
20
use CGI qw ( -utf8 );
21
use Encode qw(encode);
21
use Encode qw(encode);
22
use Carp;
22
use Carp;
23
use Digest::MD5 qw(md5_base64);
24
use Mail::Sendmail;
23
use Mail::Sendmail;
25
use MIME::QuotedPrint;
24
use MIME::QuotedPrint;
26
use MIME::Base64;
25
use MIME::Base64;
Lines 52-59 my $dbh = C4::Context->dbh; Link Here
52
51
53
if ( $email_add ) {
52
if ( $email_add ) {
54
    die "Wrong CSRF token" unless Koha::Token->new->check_csrf({
53
    die "Wrong CSRF token" unless Koha::Token->new->check_csrf({
55
        id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
54
        id     => scalar $query->cookie('CGISESSID'),
56
        secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
57
        token  => scalar $query->param('csrf_token'),
55
        token  => scalar $query->param('csrf_token'),
58
    });
56
    });
59
    my $email = Koha::Email->new();
57
    my $email = Koha::Email->new();
Lines 176-186 else { Link Here
176
        url            => "/cgi-bin/koha/basket/sendbasket.pl",
174
        url            => "/cgi-bin/koha/basket/sendbasket.pl",
177
        suggestion     => C4::Context->preference("suggestion"),
175
        suggestion     => C4::Context->preference("suggestion"),
178
        virtualshelves => C4::Context->preference("virtualshelves"),
176
        virtualshelves => C4::Context->preference("virtualshelves"),
179
        csrf_token     => Koha::Token->new->generate_csrf(
177
        csrf_token     => Koha::Token->new->generate_csrf({ id => scalar $query->cookie('CGISESSID'), }),
180
            {   id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
181
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
182
            }
183
        ),
184
    );
178
    );
185
    output_html_with_http_headers $query, $cookie, $template->output;
179
    output_html_with_http_headers $query, $cookie, $template->output;
186
}
180
}
(-)a/members/deletemem.pl (-10 / +3 lines)
Lines 25-32 use strict; Link Here
25
#use warnings; FIXME - Bug 2505
25
#use warnings; FIXME - Bug 2505
26
26
27
use CGI qw ( -utf8 );
27
use CGI qw ( -utf8 );
28
use Digest::MD5 qw(md5_base64);
29
use Encode qw( encode );
30
use C4::Context;
28
use C4::Context;
31
use C4::Output;
29
use C4::Output;
32
use C4::Auth;
30
use C4::Auth;
Lines 147-165 if ( $op eq 'delete_confirm' or $countissues > 0 or $flags->{'CHARGES'} or $is_ Link Here
147
    if ( not $countissues > 0 and not $flags->{CHARGES} ne '' and not $is_guarantor and not $deletelocal == 0 ) {
145
    if ( not $countissues > 0 and not $flags->{CHARGES} ne '' and not $is_guarantor and not $deletelocal == 0 ) {
148
        $template->param(
146
        $template->param(
149
            op         => 'delete_confirm',
147
            op         => 'delete_confirm',
150
            csrf_token => Koha::Token->new->generate_csrf(
148
            csrf_token => Koha::Token->new->generate_csrf({ id => scalar $input->cookie('CGISESSID') }),
151
                {   id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
152
                    secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
153
                }
154
            ),
155
        );
149
        );
156
    }
150
    }
157
} elsif ( $op eq 'delete_confirmed' ) {
151
} elsif ( $op eq 'delete_confirmed' ) {
158
152
159
    die "Wrong CSRF token"
153
    die "Wrong CSRF token"
160
        unless Koha::Token->new->check_csrf({
154
        unless Koha::Token->new->check_csrf( {
161
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
155
            id     => $input->cookie('CGISESSID'),
162
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
163
            token  => scalar $input->param('csrf_token'),
156
            token  => scalar $input->param('csrf_token'),
164
        });
157
        });
165
    my $patron = Koha::Patrons->find( $member );
158
    my $patron = Koha::Patrons->find( $member );
(-)a/members/member-flags.pl (-9 / +2 lines)
Lines 8-15 use strict; Link Here
8
use warnings;
8
use warnings;
9
9
10
use CGI qw ( -utf8 );
10
use CGI qw ( -utf8 );
11
use Digest::MD5 qw(md5_base64);
12
use Encode qw( encode );
13
use C4::Output;
11
use C4::Output;
14
use C4::Auth qw(:DEFAULT :EditPermissions);
12
use C4::Auth qw(:DEFAULT :EditPermissions);
15
use C4::Context;
13
use C4::Context;
Lines 48-55 if ($input->param('newflags')) { Link Here
48
46
49
    die "Wrong CSRF token"
47
    die "Wrong CSRF token"
50
        unless Koha::Token->new->check_csrf({
48
        unless Koha::Token->new->check_csrf({
51
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
49
            id     => scalar $input->cookie('CGISESSID'),
52
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
53
            token  => scalar $input->param('csrf_token'),
50
            token  => scalar $input->param('csrf_token'),
54
        });
51
        });
55
52
Lines 217-227 $template->param( Link Here
217
		is_child        => ($bor->{'category_type'} eq 'C'),
214
		is_child        => ($bor->{'category_type'} eq 'C'),
218
		activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
215
		activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''),
219
        RoutingSerials => C4::Context->preference('RoutingSerials'),
216
        RoutingSerials => C4::Context->preference('RoutingSerials'),
220
        csrf_token => Koha::Token->new->generate_csrf(
217
        csrf_token => Koha::Token->new->generate_csrf( { id => scalar $input->cookie('CGISESSID'), } ),
221
            {   id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
222
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
223
            }
224
        ),
225
		);
218
		);
226
219
227
    output_html_with_http_headers $input, $cookie, $template->output;
220
    output_html_with_http_headers $input, $cookie, $template->output;
(-)a/members/member-password.pl (-9 / +2 lines)
Lines 20-28 use Koha::Token; Link Here
20
20
21
use Koha::Patron::Categories;
21
use Koha::Patron::Categories;
22
22
23
use Digest::MD5 qw(md5_base64);
24
use Encode qw( encode );
25
26
my $input = new CGI;
23
my $input = new CGI;
27
24
28
my $theme = $input->param('theme') || "default";
25
my $theme = $input->param('theme') || "default";
Lines 69-76 if ( $newpassword && !scalar(@errors) ) { Link Here
69
66
70
    die "Wrong CSRF token"
67
    die "Wrong CSRF token"
71
        unless Koha::Token->new->check_csrf({
68
        unless Koha::Token->new->check_csrf({
72
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
69
            id     => scalar $input->cookie('CGISESSID'),
73
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
74
            token  => scalar $input->param('csrf_token'),
70
            token  => scalar $input->param('csrf_token'),
75
        });
71
        });
76
72
Lines 150-159 $template->param( Link Here
150
    activeBorrowerRelationship => ( C4::Context->preference('borrowerRelationship') ne '' ),
146
    activeBorrowerRelationship => ( C4::Context->preference('borrowerRelationship') ne '' ),
151
    minPasswordLength          => $minpw,
147
    minPasswordLength          => $minpw,
152
    RoutingSerials             => C4::Context->preference('RoutingSerials'),
148
    RoutingSerials             => C4::Context->preference('RoutingSerials'),
153
    csrf_token                 => Koha::Token->new->generate_csrf({
149
    csrf_token                 => Koha::Token->new->generate_csrf({ id => scalar $input->cookie('CGISESSID'), }),
154
        id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
155
        secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
156
    }),
157
);
150
);
158
151
159
if ( scalar(@errors) ) {
152
if ( scalar(@errors) ) {
(-)a/members/memberentry.pl (-10 / +3 lines)
Lines 25-32 use warnings; Link Here
25
# external modules
25
# external modules
26
use CGI qw ( -utf8 );
26
use CGI qw ( -utf8 );
27
use List::MoreUtils qw/uniq/;
27
use List::MoreUtils qw/uniq/;
28
use Digest::MD5 qw(md5_base64);
29
use Encode qw( encode );
30
28
31
# internal modules
29
# internal modules
32
use C4::Auth;
30
use C4::Auth;
Lines 290-297 if ($op eq 'save' || $op eq 'insert'){ Link Here
290
288
291
    die "Wrong CSRF token"
289
    die "Wrong CSRF token"
292
        unless Koha::Token->new->check_csrf({
290
        unless Koha::Token->new->check_csrf({
293
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
291
            id     => scalar $input->cookie('CGISESSID'),
294
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
295
            token  => scalar $input->param('csrf_token'),
292
            token  => scalar $input->param('csrf_token'),
296
        });
293
        });
297
294
Lines 750-761 $template->param( Link Here
750
  );
747
  );
751
748
752
# Generate CSRF token
749
# Generate CSRF token
753
$template->param(
750
$template->param( csrf_token =>
754
    csrf_token => Koha::Token->new->generate_csrf(
751
      Koha::Token->new->generate_csrf( { id => scalar $input->cookie('CGISESSID'), } ),
755
        {   id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
756
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
757
        }
758
    ),
759
);
752
);
760
753
761
# HouseboundModule data
754
# HouseboundModule data
(-)a/members/moremember.pl (-6 / +1 lines)
Lines 36-43 Link Here
36
use strict;
36
use strict;
37
#use warnings; FIXME - Bug 2505
37
#use warnings; FIXME - Bug 2505
38
use CGI qw ( -utf8 );
38
use CGI qw ( -utf8 );
39
use Digest::MD5 qw(md5_base64);
40
use Encode qw( encode );
41
use C4::Context;
39
use C4::Context;
42
use C4::Auth;
40
use C4::Auth;
43
use C4::Output;
41
use C4::Output;
Lines 277-286 my $patron_image = Koha::Patron::Images->find($data->{borrowernumber}); Link Here
277
$template->param( picture => 1 ) if $patron_image;
275
$template->param( picture => 1 ) if $patron_image;
278
# Generate CSRF token for upload and delete image buttons
276
# Generate CSRF token for upload and delete image buttons
279
$template->param(
277
$template->param(
280
    csrf_token => Koha::Token->new->generate_csrf({
278
    csrf_token => Koha::Token->new->generate_csrf({id => $input->cookie('CGISESSID'),}),
281
        id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
282
        secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
283
    }),
284
);
279
);
285
280
286
281
(-)a/opac/opac-memberentry.pl (-9 / +4 lines)
Lines 19-25 use Modern::Perl; Link Here
19
19
20
use CGI qw ( -utf8 );
20
use CGI qw ( -utf8 );
21
use Digest::MD5 qw( md5_base64 md5_hex );
21
use Digest::MD5 qw( md5_base64 md5_hex );
22
use Encode qw( encode );
23
use String::Random qw( random_string );
22
use String::Random qw( random_string );
24
23
25
use C4::Auth;
24
use C4::Auth;
Lines 200-207 elsif ( $action eq 'update' ) { Link Here
200
    my $borrower = GetMember( borrowernumber => $borrowernumber );
199
    my $borrower = GetMember( borrowernumber => $borrowernumber );
201
    die "Wrong CSRF token"
200
    die "Wrong CSRF token"
202
        unless Koha::Token->new->check_csrf({
201
        unless Koha::Token->new->check_csrf({
203
            id     => Encode::encode( 'UTF-8', $borrower->{userid} ),
202
            id     => scalar $cgi->cookie('CGISESSID'),
204
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
205
            token  => scalar $cgi->param('csrf_token'),
203
            token  => scalar $cgi->param('csrf_token'),
206
        });
204
        });
207
205
Lines 221-228 elsif ( $action eq 'update' ) { Link Here
221
            invalid_form_fields    => $invalidformfields,
219
            invalid_form_fields    => $invalidformfields,
222
            borrower               => \%borrower,
220
            borrower               => \%borrower,
223
            csrf_token             => Koha::Token->new->generate_csrf({
221
            csrf_token             => Koha::Token->new->generate_csrf({
224
                id     => Encode::encode( 'UTF-8', $borrower->{userid} ),
222
                id => scalar $cgi->cookie('CGISESSID'),
225
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
226
            }),
223
            }),
227
        );
224
        );
228
225
Lines 262-269 elsif ( $action eq 'update' ) { Link Here
262
                nochanges => 1,
259
                nochanges => 1,
263
                borrower => GetMember( borrowernumber => $borrowernumber ),
260
                borrower => GetMember( borrowernumber => $borrowernumber ),
264
                csrf_token => Koha::Token->new->generate_csrf({
261
                csrf_token => Koha::Token->new->generate_csrf({
265
                    id     => Encode::encode( 'UTF-8', $borrower->{userid} ),
262
                    id => scalar $cgi->cookie('CGISESSID'),
266
                    secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
267
                }),
263
                }),
268
            );
264
            );
269
        }
265
        }
Lines 285-292 elsif ( $action eq 'edit' ) { #Display logged in borrower's data Link Here
285
        guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
281
        guarantor => scalar Koha::Patrons->find($borrowernumber)->guarantor(),
286
        hidden => GetHiddenFields( $mandatory, 'modification' ),
282
        hidden => GetHiddenFields( $mandatory, 'modification' ),
287
        csrf_token => Koha::Token->new->generate_csrf({
283
        csrf_token => Koha::Token->new->generate_csrf({
288
            id     => Encode::encode( 'UTF-8', $borrower->{userid} ),
284
            id => scalar $cgi->cookie('CGISESSID'),
289
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
290
        }),
285
        }),
291
    );
286
    );
292
287
(-)a/opac/opac-sendbasket.pl (-8 / +3 lines)
Lines 22-28 use Modern::Perl; Link Here
22
use CGI qw ( -utf8 );
22
use CGI qw ( -utf8 );
23
use Encode qw(encode);
23
use Encode qw(encode);
24
use Carp;
24
use Carp;
25
use Digest::MD5 qw(md5_base64);
26
use Mail::Sendmail;
25
use Mail::Sendmail;
27
use MIME::QuotedPrint;
26
use MIME::QuotedPrint;
28
use MIME::Base64;
27
use MIME::Base64;
Lines 54-61 my $dbh = C4::Context->dbh; Link Here
54
53
55
if ( $email_add ) {
54
if ( $email_add ) {
56
    die "Wrong CSRF token" unless Koha::Token->new->check_csrf({
55
    die "Wrong CSRF token" unless Koha::Token->new->check_csrf({
57
        id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
56
        id     => scalar $query->cookie('CGISESSID'),
58
        secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
59
        token  => scalar $query->param('csrf_token'),
57
        token  => scalar $query->param('csrf_token'),
60
    });
58
    });
61
    my $email = Koha::Email->new();
59
    my $email = Koha::Email->new();
Lines 196-206 else { Link Here
196
        url            => "/cgi-bin/koha/opac-sendbasket.pl",
194
        url            => "/cgi-bin/koha/opac-sendbasket.pl",
197
        suggestion     => C4::Context->preference("suggestion"),
195
        suggestion     => C4::Context->preference("suggestion"),
198
        virtualshelves => C4::Context->preference("virtualshelves"),
196
        virtualshelves => C4::Context->preference("virtualshelves"),
199
        csrf_token     => Koha::Token->new->generate_csrf(
197
        csrf_token => Koha::Token->new->generate_csrf(
200
            {   id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
198
            { id => scalar $query->cookie('CGISESSID'), } ),
201
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
202
            }
203
        ),
204
    );
199
    );
205
    output_html_with_http_headers $query, $cookie, $template->output;
200
    output_html_with_http_headers $query, $cookie, $template->output;
206
}
201
}
(-)a/t/Token.t (-8 / +41 lines)
Lines 20-58 Link Here
20
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
21
22
use Modern::Perl;
22
use Modern::Perl;
23
use Test::More tests => 8;
23
use Test::More tests => 10;
24
use Time::HiRes qw|usleep|;
24
use Time::HiRes qw|usleep|;
25
use C4::Context;
25
use Koha::Token;
26
use Koha::Token;
26
27
28
C4::Context->_new_userenv('DUMMY SESSION');
29
C4::Context->set_userenv(0,42,0,'firstname','surname', 'CPL', 'Library 1', 0, ', ');
30
27
my $tokenizer = Koha::Token->new;
31
my $tokenizer = Koha::Token->new;
28
is( length( $tokenizer->generate ), 1, "Generate without parameters" );
32
is( length( $tokenizer->generate ), 1, "Generate without parameters" );
29
my $token = $tokenizer->generate({ length => 20 });
33
my $token = $tokenizer->generate({ length => 20 });
30
is( length($token), 20, "Token $token has 20 chars" );
34
is( length($token), 20, "Token $token has 20 chars" );
31
35
32
my $id = $tokenizer->generate({ length => 8 });
36
my $id = $tokenizer->generate({ lyyGength => 8 });
33
my $secr = $tokenizer->generate({ length => 32 });
37
my $csrftoken = $tokenizer->generate_csrf({ id => $id });
34
my $csrftoken = $tokenizer->generate_csrf({ id => $id, secret => $secr });
35
isnt( length($csrftoken), 0, "Token $csrftoken should not be empty" );
38
isnt( length($csrftoken), 0, "Token $csrftoken should not be empty" );
36
39
37
is( $tokenizer->check, undef, "Check without any parameters" );
40
is( $tokenizer->check, undef, "Check without any parameters" );
38
my $result = $tokenizer->check_csrf({
41
my $result = $tokenizer->check_csrf({
39
    id => $id, secret => $secr, token => $csrftoken,
42
    id => $id, token => $csrftoken,
40
});
43
});
41
is( $result, 1, "CSRF token verified" );
44
is( $result, 1, "CSRF token verified" );
42
45
43
$result = $tokenizer->check({
46
$result = $tokenizer->check({
44
    type => 'CSRF', id => $id, secret => $secr, token => $token,
47
    type => 'CSRF', id => $id, token => $token,
45
});
48
});
46
isnt( $result, 1, "This token is no CSRF token" );
49
isnt( $result, 1, "This token is no CSRF token" );
47
50
48
# Test MaxAge parameter
51
# Test MaxAge parameter
49
my $age = 1; # 1 second
52
my $age = 1; # 1 second
50
$result = $tokenizer->check_csrf({
53
$result = $tokenizer->check_csrf({
51
    id => $id, secret => $secr, token => $csrftoken, MaxAge => $age,
54
    id => $id, token => $csrftoken, MaxAge => $age,
52
});
55
});
53
is( $result, 1, "CSRF token still valid within one second" );
56
is( $result, 1, "CSRF token still valid within one second" );
54
usleep $age * 1000000 * 2; # micro (millionth) seconds + 100%
57
usleep $age * 1000000 * 2; # micro (millionth) seconds + 100%
55
$result = $tokenizer->check_csrf({
58
$result = $tokenizer->check_csrf({
56
    id => $id, secret => $secr, token => $csrftoken, MaxAge => $age,
59
    id => $id, token => $csrftoken, MaxAge => $age,
57
});
60
});
58
isnt( $result, 1, "CSRF token expired after one second" );
61
isnt( $result, 1, "CSRF token expired after one second" );
62
63
subtest 'Same id (cookie CGISESSID) with an other logged in user' => sub {
64
    plan tests => 2;
65
    $csrftoken = $tokenizer->generate_csrf({ id => $id });
66
    $result = $tokenizer->check_csrf({
67
        id => $id, token => $csrftoken,
68
    });
69
    is( $result, 1, "CSRF token verified" );
70
    C4::Context->set_userenv(0,43,0,'firstname','surname', 'CPL', 'Library 1', 0, ', ');
71
    $result = $tokenizer->check_csrf({
72
        id => $id, token => $csrftoken,
73
    });
74
    is( $result, '', "CSRF token is not verified if another logged in user is using the same id" );
75
};
76
77
subtest 'Same logged in user with another session (cookie CGISESSID)' => sub {
78
    plan tests => 2;
79
    C4::Context->set_userenv(0,42,0,'firstname','surname', 'CPL', 'Library 1', 0, ', ');
80
    $csrftoken = $tokenizer->generate_csrf({ id => $id });
81
    $result = $tokenizer->check_csrf({
82
        id => $id, token => $csrftoken,
83
    });
84
    is( $result, 1, "CSRF token verified" );
85
    # Get another session id
86
    $id = $tokenizer->generate({ lyyGength => 8 });
87
    $result = $tokenizer->check_csrf({
88
        id => $id, token => $csrftoken,
89
    });
90
    is( $result, '', "CSRF token is not verified if another session is used" );
91
};
(-)a/tools/import_borrowers.pl (-7 / +2 lines)
Lines 59-66 use Text::CSV; Link Here
59
# č
59
# č
60
60
61
use CGI qw ( -utf8 );
61
use CGI qw ( -utf8 );
62
use Digest::MD5 qw(md5_base64);
63
use Encode qw( encode );
64
62
65
my (@errors, @feedback);
63
my (@errors, @feedback);
66
my $extended = C4::Context->preference('ExtendedPatronAttributes');
64
my $extended = C4::Context->preference('ExtendedPatronAttributes');
Lines 112-119 $template->param( SCRIPT_NAME => '/cgi-bin/koha/tools/import_borrowers.pl' ); Link Here
112
if ( $uploadborrowers && length($uploadborrowers) > 0 ) {
110
if ( $uploadborrowers && length($uploadborrowers) > 0 ) {
113
    die "Wrong CSRF token"
111
    die "Wrong CSRF token"
114
        unless Koha::Token->new->check_csrf({
112
        unless Koha::Token->new->check_csrf({
115
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
113
            id     => scalar $input->cookie('CGISESSID'),
116
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
117
            token  => scalar $input->param('csrf_token'),
114
            token  => scalar $input->param('csrf_token'),
118
        });
115
        });
119
116
Lines 391-399 if ( $uploadborrowers && length($uploadborrowers) > 0 ) { Link Here
391
388
392
    $template->param(
389
    $template->param(
393
        csrf_token => Koha::Token->new->generate_csrf(
390
        csrf_token => Koha::Token->new->generate_csrf(
394
            {   id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
391
            { id => scalar $input->cookie('CGISESSID'), }
395
                secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
396
            }
397
        ),
392
        ),
398
    );
393
    );
399
394
(-)a/tools/picture-upload.pl (-9 / +3 lines)
Lines 25-32 use File::Temp; Link Here
25
use File::Copy;
25
use File::Copy;
26
use CGI qw ( -utf8 );
26
use CGI qw ( -utf8 );
27
use GD;
27
use GD;
28
use Digest::MD5 qw(md5_base64);
29
use Encode qw( encode );
30
use C4::Context;
28
use C4::Context;
31
use C4::Auth;
29
use C4::Auth;
32
use C4::Output;
30
use C4::Output;
Lines 88-95 if ( ( $op eq 'Upload' ) && $uploadfile ) { Link Here
88
86
89
    die "Wrong CSRF token"
87
    die "Wrong CSRF token"
90
        unless Koha::Token->new->check_csrf({
88
        unless Koha::Token->new->check_csrf({
91
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
89
            id     => scalar $input->cookie('CGISESSID'),
92
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
93
            token  => scalar $input->param('csrf_token'),
90
            token  => scalar $input->param('csrf_token'),
94
        });
91
        });
95
92
Lines 176-183 elsif ( ( $op eq 'Upload' ) && !$uploadfile ) { Link Here
176
elsif ( $op eq 'Delete' ) {
173
elsif ( $op eq 'Delete' ) {
177
    die "Wrong CSRF token"
174
    die "Wrong CSRF token"
178
        unless Koha::Token->new->check_csrf({
175
        unless Koha::Token->new->check_csrf({
179
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
176
            id     => scalar $input->cookie('CGISESSID'),
180
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
181
            token  => scalar $input->param('csrf_token'),
177
            token  => scalar $input->param('csrf_token'),
182
        });
178
        });
183
179
Lines 195-202 if ( $borrowernumber && !%errors && !$template->param('ERRORS') ) { Link Here
195
else {
191
else {
196
    $template->param(
192
    $template->param(
197
        csrf_token => Koha::Token->new->generate_csrf({
193
        csrf_token => Koha::Token->new->generate_csrf({
198
            id     => Encode::encode( 'UTF-8', C4::Context->userenv->{id} ),
194
            id => scalar $input->cookie('CGISESSID'),
199
            secret => md5_base64( Encode::encode( 'UTF-8', C4::Context->config('pass') ) ),
200
        }),
195
        }),
201
    );
196
    );
202
    output_html_with_http_headers $input, $cookie, $template->output;
197
    output_html_with_http_headers $input, $cookie, $template->output;
203
- 

Return to bug 18124