File Coverage

blib/lib/Authen/Simple/Passwd.pm
Criterion Covered Total %
statement 55 69 79.7
branch 18 44 40.9
condition 2 6 33.3
subroutine 11 11 100.0
pod 2 2 100.0
total 88 132 66.6


line stmt bran cond sub pod time code
1             package Authen::Simple::Passwd;
2              
3 2     2   1871 use strict;
  2         5  
  2         78  
4 2     2   11 use warnings;
  2         4  
  2         66  
5 2     2   20 use bytes;
  2         4  
  2         15  
6 2     2   51 use base 'Authen::Simple::Adapter';
  2         3  
  2         1929  
7              
8 2     2   98901 use Carp qw[];
  2         6  
  2         29  
9 2     2   10 use Config qw[];
  2         3  
  2         30  
10 2     2   12 use Fcntl qw[LOCK_SH];
  2         4  
  2         107  
11 2     2   1767 use IO::File qw[O_RDONLY];
  2         6105  
  2         156  
12 2     2   15 use Params::Validate qw[];
  2         3  
  2         1687  
13              
14             our $VERSION = 0.6;
15              
16             __PACKAGE__->options({
17             path => {
18             type => Params::Validate::SCALAR,
19             optional => 1
20             },
21             flock => {
22             type => Params::Validate::SCALAR,
23             default => ( $Config::Config{d_flock} ) ? 1 : 0,
24             optional => 1
25             },
26             passwd => { # deprecated
27             type => Params::Validate::SCALAR,
28             optional => 1
29             },
30             allow => { # deprecated
31             type => Params::Validate::ARRAYREF,
32             optional => 1,
33             }
34             });
35              
36             sub init {
37 1     1 1 932 my ( $self, $params ) = @_;
38              
39 1   33     7 my $path = $params->{path} ||= delete $params->{passwd};
40              
41 1 50       67 unless ( -e $path ) {
42 0         0 Carp::croak( qq/Passwd path '$path' does not exist./ );
43             }
44              
45 1 50       8 unless ( -f _ ) {
46 0         0 Carp::croak( qq/Passwd path '$path' is not a file./ );
47             }
48              
49 1 50       7 unless ( -r _ ) {
50 0         0 Carp::croak( qq/Passwd path '$path' is not readable by effective uid '$>'./ );
51             }
52              
53 1         10 return $self->SUPER::init($params);
54             }
55              
56             sub check {
57 6     6 1 5091 my ( $self, $username, $password ) = @_;
58              
59 6 100       25 if ( $username =~ /^-/ ) {
60              
61 1 50       7 $self->log->debug( qq/User '$username' begins with a hyphen which is not allowed./ )
62             if $self->log;
63              
64 1         17 return 0;
65             }
66              
67 5         19 my ( $path, $fh, $encrypted ) = ( $self->path, undef, undef );
68              
69 5 50       56 unless ( $fh = IO::File->new( $path, O_RDONLY ) ) {
70              
71 0 0       0 $self->log->error( qq/Failed to open passwd '$path'. Reason: '$!'/ )
72             if $self->log;
73              
74 0         0 return 0;
75             }
76              
77 5 50 33     788 unless ( !$self->flock || flock( $fh, LOCK_SH ) ) {
78              
79 0 0       0 $self->log->error( qq/Failed to obtain a shared lock on passwd '$path'. Reason: '$!'/ )
80             if $self->log;
81              
82 0         0 return 0;
83             }
84              
85 5         560 while ( defined( $_ = $fh->getline ) ) {
86              
87 15 50       743 next if /^#/;
88 15 50       183 next if /^\s+/;
89              
90 15         25 chop;
91              
92 15         56 my (@credentials) = split( /:/, $_, 3 );
93              
94 15 100       357 if ( $credentials[0] eq $username ) {
95              
96 5         7 $encrypted = $credentials[1];
97              
98 5 50       18 $self->log->debug( qq/Found user '$username' in passwd '$path'./ )
99             if $self->log;
100              
101 5         85 last;
102             }
103             }
104              
105 5 50       32 unless ( $fh->close ) {
106              
107 0 0       0 $self->log->warn( qq/Failed to close passwd '$path'. Reason: '$!'/ )
108             if $self->log;
109             }
110              
111 5 50       129 unless ( defined $encrypted ) {
112              
113 0 0       0 $self->log->debug( qq/User '$username' was not found in passwd '$path'./ )
114             if $self->log;
115              
116 0         0 return 0;
117             }
118              
119 5 50       13 unless ( length $encrypted ) {
120              
121 0 0       0 $self->log->debug( qq/Encrypted password for user '$username' is null./ )
122             if $self->log;
123              
124 0         0 return 0;
125             }
126              
127 5 50       22 unless ( $self->check_password( $password, $encrypted ) ) {
128              
129 0 0       0 $self->log->debug( qq/Failed to authenticate user '$username'. Reason: 'Invalid credentials'/ )
130             if $self->log;
131              
132 0         0 return 0;
133             }
134              
135 5 50       34552 $self->log->debug( qq/Successfully authenticated user '$username'./ )
136             if $self->log;
137              
138 5         190 return 1;
139             }
140              
141             1;
142              
143             __END__