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

(-)a/C4/Auth.pm (-5 / +49 lines)
Lines 23-28 use Digest::MD5 qw(md5_base64); Link Here
23
use JSON qw/encode_json decode_json/;
23
use JSON qw/encode_json decode_json/;
24
use URI::Escape;
24
use URI::Escape;
25
use CGI::Session;
25
use CGI::Session;
26
use Crypt::Eksblowfish::Bcrypt qw(bcrypt en_base64);
27
use Crypt::Random::Source;
26
28
27
require Exporter;
29
require Exporter;
28
use C4::Context;
30
use C4::Context;
Lines 47-53 BEGIN { Link Here
47
    @ISA         = qw(Exporter);
49
    @ISA         = qw(Exporter);
48
    @EXPORT      = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions);
50
    @EXPORT      = qw(&checkauth &get_template_and_user &haspermission &get_user_subpermissions);
49
    @EXPORT_OK   = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions
51
    @EXPORT_OK   = qw(&check_api_auth &get_session &check_cookie_auth &checkpw &get_all_subpermissions &get_user_subpermissions
50
                      ParseSearchHistoryCookie
52
                      ParseSearchHistoryCookie hash_password
51
                   );
53
                   );
52
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
54
    %EXPORT_TAGS = ( EditPermissions => [qw(get_all_subpermissions get_user_subpermissions)] );
53
    $ldap        = C4::Context->config('useldapserver') || 0;
55
    $ldap        = C4::Context->config('useldapserver') || 0;
Lines 1464-1469 sub get_session { Link Here
1464
    return $session;
1466
    return $session;
1465
}
1467
}
1466
1468
1469
# Using Bcrypt method for hashing. This can be changed to something else in future, if needed.
1470
sub hash_password {
1471
    my $password = shift;
1472
1473
    # Generate a salt if one is not passed
1474
    my $settings = shift;
1475
    unless( defined $settings ){ # if there are no settings, we need to create a salt and append settings
1476
    # Set the cost to 8 and append a NULL
1477
      $settings = '$2a$08$'.en_base64(generate_salt('strong'));
1478
    }
1479
    # Encrypt it
1480
    return bcrypt($password, $settings);
1481
}
1482
1483
# Return a random salt
1484
sub generate_salt {
1485
    my ($type) = @_;
1486
1487
        if ($type eq 'strong') {
1488
                return Crypt::Random::Source::get_strong(16);
1489
        } else {
1490
                return Crypt::Random::Source::get_weak(16);
1491
        }
1492
}
1493
1467
sub checkpw {
1494
sub checkpw {
1468
1495
1469
    my ( $dbh, $userid, $password, $query ) = @_;
1496
    my ( $dbh, $userid, $password, $query ) = @_;
Lines 1489-1498 sub checkpw { Link Here
1489
      );
1516
      );
1490
    $sth->execute($userid);
1517
    $sth->execute($userid);
1491
    if ( $sth->rows ) {
1518
    if ( $sth->rows ) {
1492
        my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname,
1519
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1493
            $surname, $branchcode, $flags )
1520
            $surname, $branchcode, $flags )
1494
          = $sth->fetchrow;
1521
          = $sth->fetchrow;
1495
        if ( md5_base64($password) eq $md5password and $md5password ne "!") {
1522
1523
        # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5
1524
        my $hash;
1525
        if ( substr($stored_hash,0,2) eq '$2') {
1526
            $hash = hash_password($password, $stored_hash);
1527
        } else {
1528
            $hash = md5_base64($password);
1529
        }
1530
        if ( $hash eq $stored_hash and $stored_hash ne "!") {
1496
1531
1497
            C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
1532
            C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
1498
                $firstname, $surname, $branchcode, $flags );
1533
                $firstname, $surname, $branchcode, $flags );
Lines 1505-1514 sub checkpw { Link Here
1505
      );
1540
      );
1506
    $sth->execute($userid);
1541
    $sth->execute($userid);
1507
    if ( $sth->rows ) {
1542
    if ( $sth->rows ) {
1508
        my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname,
1543
        my ( $stored_hash, $cardnumber, $borrowernumber, $userid, $firstname,
1509
            $surname, $branchcode, $flags )
1544
            $surname, $branchcode, $flags )
1510
          = $sth->fetchrow;
1545
          = $sth->fetchrow;
1511
        if ( md5_base64($password) eq $md5password ) {
1546
1547
        # check what encryption algorithm was implemented: Bcrypt - if the hash starts with '$2' it is Bcrypt else md5
1548
        my $hash;
1549
        if ( substr($stored_hash,0,2) eq '$2') {
1550
            $hash = hash_password($password, $stored_hash);
1551
        } else {
1552
            $hash = md5_base64($password);
1553
        }
1554
1555
        if ( $hash eq $stored_hash ) {
1512
1556
1513
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1557
            C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
1514
                $firstname, $surname, $branchcode, $flags );
1558
                $firstname, $surname, $branchcode, $flags );
(-)a/C4/Members.pm (-29 / +6 lines)
Lines 24-30 use strict; Link Here
24
#use warnings; FIXME - Bug 2505
24
#use warnings; FIXME - Bug 2505
25
use C4::Context;
25
use C4::Context;
26
use C4::Dates qw(format_date_in_iso format_date);
26
use C4::Dates qw(format_date_in_iso format_date);
27
use Digest::MD5 qw(md5_base64);
28
use String::Random qw( random_string );
27
use String::Random qw( random_string );
29
use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/;
28
use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/;
30
use C4::Log; # logaction
29
use C4::Log; # logaction
Lines 40-45 use DateTime; Link Here
40
use DateTime::Format::DateParse;
39
use DateTime::Format::DateParse;
41
use Koha::DateUtils;
40
use Koha::DateUtils;
42
use Text::Unaccent qw( unac_string );
41
use Text::Unaccent qw( unac_string );
42
use C4::Auth qw(hash_password);
43
43
44
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
44
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
45
45
Lines 250-256 sub Search { Link Here
250
                $filter = [ $filter ];
250
                $filter = [ $filter ];
251
                push @$filter, {"borrowernumber"=>$matching_records};
251
                push @$filter, {"borrowernumber"=>$matching_records};
252
            }
252
            }
253
		}
253
        }
254
    }
254
    }
255
255
256
    # $showallbranches was not used at the time SearchMember() was mainstreamed into Search().
256
    # $showallbranches was not used at the time SearchMember() was mainstreamed into Search().
Lines 283-289 sub Search { Link Here
283
    }
283
    }
284
    $searchtype ||= "start_with";
284
    $searchtype ||= "start_with";
285
285
286
	return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype );
286
    return SearchInTable( "borrowers", $filter, $orderby, $limit, $columns_out, $search_on_fields, $searchtype );
287
}
287
}
288
288
289
=head2 GetMemberDetails
289
=head2 GetMemberDetails
Lines 718-727 sub ModMember { Link Here
718
        if ($data{password} eq '****' or $data{password} eq '') {
718
        if ($data{password} eq '****' or $data{password} eq '') {
719
            delete $data{password};
719
            delete $data{password};
720
        } else {
720
        } else {
721
            $data{password} = md5_base64($data{password});
721
            $data{password} = hash_password($data{password});
722
        }
722
        }
723
    }
723
    }
724
	my $execute_success=UpdateInTable("borrowers",\%data);
724
    my $execute_success=UpdateInTable("borrowers",\%data);
725
    if ($execute_success) { # only proceed if the update was a success
725
    if ($execute_success) { # only proceed if the update was a success
726
        # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
726
        # ok if its an adult (type) it may have borrowers that depend on it as a guarantor
727
        # so when we update information for an adult we should check for guarantees and update the relevant part
727
        # so when we update information for an adult we should check for guarantees and update the relevant part
Lines 767-776 sub AddMember { Link Here
767
    }
767
    }
768
768
769
    # create a disabled account if no password provided
769
    # create a disabled account if no password provided
770
    $data{'password'} = ($data{'password'})? md5_base64($data{'password'}) : '!';
770
    $data{'password'} = ($data{'password'})? hash_password($data{'password'}) : '!';
771
    $data{'borrowernumber'}=InsertInTable("borrowers",\%data);
771
    $data{'borrowernumber'}=InsertInTable("borrowers",\%data);
772
772
773
774
    # mysql_insertid is probably bad.  not necessarily accurate and mysql-specific at best.
773
    # mysql_insertid is probably bad.  not necessarily accurate and mysql-specific at best.
775
    logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog");
774
    logaction("MEMBERS", "CREATE", $data{'borrowernumber'}, "") if C4::Context->preference("BorrowersLog");
776
    
775
    
Lines 1439-1466 sub GetExpiryDate { Link Here
1439
    }
1438
    }
1440
}
1439
}
1441
1440
1442
=head2 checkuserpassword (OUEST-PROVENCE)
1443
1444
check for the password and login are not used
1445
return the number of record 
1446
0=> NOT USED 1=> USED
1447
1448
=cut
1449
1450
sub checkuserpassword {
1451
    my ( $borrowernumber, $userid, $password ) = @_;
1452
    $password = md5_base64($password);
1453
    my $dbh = C4::Context->dbh;
1454
    my $sth =
1455
      $dbh->prepare(
1456
"Select count(*) from borrowers where borrowernumber !=? and userid =? and password=? "
1457
      );
1458
    $sth->execute( $borrowernumber, $userid, $password );
1459
    my $number_rows = $sth->fetchrow;
1460
    return $number_rows;
1461
1462
}
1463
1464
=head2 GetborCatFromCatType
1441
=head2 GetborCatFromCatType
1465
1442
1466
  ($codes_arrayref, $labels_hashref) = &GetborCatFromCatType();
1443
  ($codes_arrayref, $labels_hashref) = &GetborCatFromCatType();
(-)a/members/member-password.pl (-1 / +1 lines)
Lines 55-61 my $minpw = C4::Context->preference('minPasswordLength'); Link Here
55
push(@errors,'SHORTPASSWORD') if( $newpassword && $minpw && (length($newpassword) < $minpw ) );
55
push(@errors,'SHORTPASSWORD') if( $newpassword && $minpw && (length($newpassword) < $minpw ) );
56
56
57
if ( $newpassword  && !scalar(@errors) ) {
57
if ( $newpassword  && !scalar(@errors) ) {
58
    my $digest=md5_base64($input->param('newpassword'));
58
    my $digest=C4::Auth::hash_password($input->param('newpassword'));
59
    my $uid = $input->param('newuserid');
59
    my $uid = $input->param('newuserid');
60
    my $dbh=C4::Context->dbh;
60
    my $dbh=C4::Context->dbh;
61
    if (changepassword($uid,$member,$digest)) {
61
    if (changepassword($uid,$member,$digest)) {
(-)a/opac/opac-passwd.pl (-4 / +10 lines)
Lines 29-34 use Digest::MD5 qw(md5_base64); Link Here
29
use C4::Circulation;
29
use C4::Circulation;
30
use C4::Members;
30
use C4::Members;
31
use C4::Output;
31
use C4::Output;
32
use C4::Auth qw(hash_password);
32
33
33
my $query = new CGI;
34
my $query = new CGI;
34
my $dbh   = C4::Context->dbh;
35
my $dbh   = C4::Context->dbh;
Lines 57-63 if ( C4::Context->preference("OpacPasswordChange") ) { Link Here
57
            if ( $query->param('Newkey') eq $query->param('Confirm')
58
            if ( $query->param('Newkey') eq $query->param('Confirm')
58
                && length( $query->param('Confirm') ) >= $minpasslen )
59
                && length( $query->param('Confirm') ) >= $minpasslen )
59
            {    # Record password
60
            {    # Record password
60
                my $clave = md5_base64( $query->param('Newkey') );
61
                my $clave = hash_password( $query->param('Newkey') );
61
                $sth->execute( $clave, $borrowernumber );
62
                $sth->execute( $clave, $borrowernumber );
62
                $template->param( 'password_updated' => '1' );
63
                $template->param( 'password_updated' => '1' );
63
                $template->param( 'borrowernumber'   => $borrowernumber );
64
                $template->param( 'borrowernumber'   => $borrowernumber );
Lines 113-120 sub goodkey { Link Here
113
      $dbh->prepare("SELECT password FROM borrowers WHERE borrowernumber=?");
114
      $dbh->prepare("SELECT password FROM borrowers WHERE borrowernumber=?");
114
    $sth->execute($borrowernumber);
115
    $sth->execute($borrowernumber);
115
    if ( $sth->rows ) {
116
    if ( $sth->rows ) {
116
        my ($md5password) = $sth->fetchrow;
117
        my $hash;
117
        if ( md5_base64($key) eq $md5password ) { return 1; }
118
        my ($stored_hash) = $sth->fetchrow;
119
        if ( substr($stored_hash,0,2) eq '$2') {
120
            $hash = hash_password($key, $stored_hash);
121
        } else {
122
            $hash = md5_base64($key);
123
        }
124
        if ( $hash eq $stored_hash ) { return 1; }
118
        else { return 0; }
125
        else { return 0; }
119
    }
126
    }
120
    else { return 0; }
127
    else { return 0; }
121
- 

Return to bug 9611