package Authen::Simple::Passwd;
use strict;
use warnings;
use bytes;
use base 'Authen::Simple::Adapter';
use Carp qw[];
use Config qw[];
use Fcntl qw[LOCK_SH];
use IO::File qw[O_RDONLY];
use Params::Validate qw[];
our $VERSION = 0.6;
__PACKAGE__->options({
path => {
type => Params::Validate::SCALAR,
optional => 1
},
flock => {
type => Params::Validate::SCALAR,
default => ( $Config::Config{d_flock} ) ? 1 : 0,
optional => 1
},
passwd => { # deprecated
type => Params::Validate::SCALAR,
optional => 1
},
allow => { # deprecated
type => Params::Validate::ARRAYREF,
optional => 1,
}
});
sub init {
my ( $self, $params ) = @_;
my $path = $params->{path} ||= delete $params->{passwd};
unless ( -e $path ) {
Carp::croak( qq/Passwd path '$path' does not exist./ );
}
unless ( -f _ ) {
Carp::croak( qq/Passwd path '$path' is not a file./ );
}
unless ( -r _ ) {
Carp::croak( qq/Passwd path '$path' is not readable by effective uid '$>'./ );
}
return $self->SUPER::init($params);
}
sub check {
my ( $self, $username, $password ) = @_;
if ( $username =~ /^-/ ) {
$self->log->debug( qq/User '$username' begins with a hyphen which is not allowed./ )
if $self->log;
return 0;
}
my ( $path, $fh, $encrypted ) = ( $self->path, undef, undef );
unless ( $fh = IO::File->new( $path, O_RDONLY ) ) {
$self->log->error( qq/Failed to open passwd '$path'. Reason: '$!'/ )
if $self->log;
return 0;
}
unless ( !$self->flock || flock( $fh, LOCK_SH ) ) {
$self->log->error( qq/Failed to obtain a shared lock on passwd '$path'. Reason: '$!'/ )
if $self->log;
return 0;
}
while ( defined( $_ = $fh->getline ) ) {
next if /^#/;
next if /^\s+/;
chop;
my (@credentials) = split( /:/, $_, 3 );
if ( $credentials[0] eq $username ) {
$encrypted = $credentials[1];
$self->log->debug( qq/Found user '$username' in passwd '$path'./ )
if $self->log;
=1= |