| Filename | /mnt/catalyst/koha/Koha/AuthUtils.pm |
| Statements | Executed 11 statements in 10.3ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 10.3ms | 20.3ms | Koha::AuthUtils::BEGIN@21 |
| 1 | 1 | 1 | 451µs | 606µs | Koha::AuthUtils::BEGIN@20 |
| 1 | 1 | 1 | 9µs | 29µs | Koha::AuthUtils::BEGIN@22 |
| 1 | 1 | 1 | 9µs | 74µs | Koha::AuthUtils::BEGIN@24 |
| 0 | 0 | 0 | 0s | 0s | Koha::AuthUtils::generate_salt |
| 0 | 0 | 0 | 0s | 0s | Koha::AuthUtils::hash_password |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Koha::AuthUtils; | ||||
| 2 | |||||
| 3 | # Copyright 2013 Catalyst IT | ||||
| 4 | # | ||||
| 5 | # This file is part of Koha. | ||||
| 6 | # | ||||
| 7 | # Koha is free software; you can redistribute it and/or modify it | ||||
| 8 | # under the terms of the GNU General Public License as published by | ||||
| 9 | # the Free Software Foundation; either version 3 of the License, or | ||||
| 10 | # (at your option) any later version. | ||||
| 11 | # | ||||
| 12 | # Koha is distributed in the hope that it will be useful, but | ||||
| 13 | # WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| 15 | # GNU General Public License for more details. | ||||
| 16 | # | ||||
| 17 | # You should have received a copy of the GNU General Public License | ||||
| 18 | # along with Koha; if not, see <http://www.gnu.org/licenses>. | ||||
| 19 | |||||
| 20 | 2 | 34µs | 2 | 760µs | # spent 606µs (451+155) within Koha::AuthUtils::BEGIN@20 which was called:
# once (451µs+155µs) by C4::Members::BEGIN@43 at line 20 # spent 606µs making 1 call to Koha::AuthUtils::BEGIN@20
# spent 155µs making 1 call to Modern::Perl::import |
| 21 | 2 | 9.79ms | 2 | 20.3ms | # spent 20.3ms (10.3+9.93) within Koha::AuthUtils::BEGIN@21 which was called:
# once (10.3ms+9.93ms) by C4::Members::BEGIN@43 at line 21 # spent 20.3ms making 1 call to Koha::AuthUtils::BEGIN@21
# spent 38µs making 1 call to Exporter::import |
| 22 | 2 | 25µs | 2 | 49µs | # spent 29µs (9+20) within Koha::AuthUtils::BEGIN@22 which was called:
# once (9µs+20µs) by C4::Members::BEGIN@43 at line 22 # spent 29µs making 1 call to Koha::AuthUtils::BEGIN@22
# spent 20µs making 1 call to Exporter::import |
| 23 | |||||
| 24 | 2 | 419µs | 2 | 138µs | # spent 74µs (9+65) within Koha::AuthUtils::BEGIN@24 which was called:
# once (9µs+65µs) by C4::Members::BEGIN@43 at line 24 # spent 74µs making 1 call to Koha::AuthUtils::BEGIN@24
# spent 65µs making 1 call to base::import |
| 25 | |||||
| 26 | 1 | 500ns | our $VERSION = '1.01'; | ||
| 27 | 1 | 700ns | our @EXPORT_OK = qw(hash_password); | ||
| 28 | |||||
| 29 | =head1 NAME | ||||
| 30 | |||||
| 31 | Koha::AuthUtils - utility routines for authentication | ||||
| 32 | |||||
| 33 | =head1 SYNOPSIS | ||||
| 34 | |||||
| 35 | use Koha::AuthUtils qw/hash_password/; | ||||
| 36 | my $hash = hash_password($password); | ||||
| 37 | |||||
| 38 | =head1 DESCRIPTION | ||||
| 39 | |||||
| 40 | This module provides utility functions related to managing | ||||
| 41 | user passwords. | ||||
| 42 | |||||
| 43 | =head1 FUNCTIONS | ||||
| 44 | |||||
| 45 | =head2 hash_password | ||||
| 46 | |||||
| 47 | my $hash = Koha::AuthUtils::hash_password($password, $settings); | ||||
| 48 | |||||
| 49 | =cut | ||||
| 50 | |||||
| 51 | # Using Bcrypt method for hashing. This can be changed to something else in future, if needed. | ||||
| 52 | sub hash_password { | ||||
| 53 | my $password = shift; | ||||
| 54 | |||||
| 55 | # Generate a salt if one is not passed | ||||
| 56 | my $settings = shift; | ||||
| 57 | unless( defined $settings ){ # if there are no settings, we need to create a salt and append settings | ||||
| 58 | # Set the cost to 8 and append a NULL | ||||
| 59 | $settings = '$2a$08$'.en_base64(generate_salt('weak', 16)); | ||||
| 60 | } | ||||
| 61 | # Encrypt it | ||||
| 62 | return bcrypt($password, $settings); | ||||
| 63 | } | ||||
| 64 | |||||
| 65 | =head2 generate_salt | ||||
| 66 | |||||
| 67 | my $salt = Koha::Auth::generate_salt($strength, $length); | ||||
| 68 | |||||
| 69 | =over | ||||
| 70 | |||||
| 71 | =item strength | ||||
| 72 | |||||
| 73 | For general password salting a C<$strength> of C<weak> is recommend, | ||||
| 74 | For generating a server-salt a C<$strength> of C<strong> is recommended | ||||
| 75 | |||||
| 76 | 'strong' uses /dev/random which may block until sufficient entropy is acheived. | ||||
| 77 | 'weak' uses /dev/urandom and is non-blocking. | ||||
| 78 | |||||
| 79 | =item length | ||||
| 80 | |||||
| 81 | C<$length> is a positive integer which specifies the desired length of the returned string | ||||
| 82 | |||||
| 83 | =back | ||||
| 84 | |||||
| 85 | =cut | ||||
| 86 | |||||
| 87 | |||||
| 88 | # the implementation of generate_salt is loosely based on Crypt::Random::Provider::File | ||||
| 89 | sub generate_salt { | ||||
| 90 | # strength is 'strong' or 'weak' | ||||
| 91 | # length is number of bytes to read, positive integer | ||||
| 92 | my ($strength, $length) = @_; | ||||
| 93 | |||||
| 94 | my $source; | ||||
| 95 | |||||
| 96 | if( $length < 1 ){ | ||||
| 97 | die "non-positive strength of '$strength' passed to Koha::AuthUtils::generate_salt\n"; | ||||
| 98 | } | ||||
| 99 | |||||
| 100 | if( $strength eq "strong" ){ | ||||
| 101 | $source = '/dev/random'; # blocking | ||||
| 102 | } else { | ||||
| 103 | unless( $strength eq 'weak' ){ | ||||
| 104 | warn "unsuppored strength of '$strength' passed to Koha::AuthUtils::generate_salt, defaulting to 'weak'\n"; | ||||
| 105 | } | ||||
| 106 | $source = '/dev/urandom'; # non-blocking | ||||
| 107 | } | ||||
| 108 | |||||
| 109 | sysopen SOURCE, $source, O_RDONLY | ||||
| 110 | or die "failed to open source '$source' in Koha::AuthUtils::generate_salt\n"; | ||||
| 111 | |||||
| 112 | # $bytes is the bytes just read | ||||
| 113 | # $string is the concatenation of all the bytes read so far | ||||
| 114 | my( $bytes, $string ) = ("", ""); | ||||
| 115 | |||||
| 116 | # keep reading until we have $length bytes in $strength | ||||
| 117 | while( length($string) < $length ){ | ||||
| 118 | # return the number of bytes read, 0 (EOF), or -1 (ERROR) | ||||
| 119 | my $return = sysread SOURCE, $bytes, $length - length($string); | ||||
| 120 | |||||
| 121 | # if no bytes were read, keep reading (if using /dev/random it is possible there was insufficient entropy so this may block) | ||||
| 122 | next unless $return; | ||||
| 123 | if( $return == -1 ){ | ||||
| 124 | die "error while reading from $source in Koha::AuthUtils::generate_salt\n"; | ||||
| 125 | } | ||||
| 126 | |||||
| 127 | $string .= $bytes; | ||||
| 128 | } | ||||
| 129 | |||||
| 130 | close SOURCE; | ||||
| 131 | return $string; | ||||
| 132 | } | ||||
| 133 | 1 | 3µs | 1; | ||
| 134 | |||||
| 135 | __END__ |