File Coverage

blib/lib/Connector/Builtin/Authentication/Password.pm
Criterion Covered Total %
statement 62 74 83.7
branch 18 24 75.0
condition 2 6 33.3
subroutine 9 10 90.0
pod 3 3 100.0
total 94 117 80.3


line stmt bran cond sub pod time code
1             # Connector::Builtin::Authentication::Password
2             #
3             # Check passwords against a unix style password file
4             #
5              
6             use strict;
7 1     1   137395 use warnings;
  1         10  
  1         27  
8 1     1   6 use English;
  1         2  
  1         26  
9 1     1   4 use Data::Dumper;
  1         2  
  1         6  
10 1     1   903  
  1         6617  
  1         79  
11             use Moose;
12 1     1   452 extends 'Connector::Builtin';
  1         419293  
  1         6  
13              
14             my $self = shift;
15              
16 0     0   0 if (! -r $self->{LOCATION}) {
17             confess("Cannot open input file " . $self->{LOCATION} . " for reading.");
18 0 0       0 }
19 0         0  
20             return 1;
21             }
22 0         0  
23             my $self = shift;
24             my $arg = shift;
25             my $params = shift;
26 7     7 1 22  
27 7         9 my @path = $self->_build_path( $arg );
28 7         10 my $user = shift @path;
29              
30 7         19 my $password = $params->{password};
31 7         12  
32              
33 7         12 if (!$user) {
34             $self->log()->error('No username');
35             die "no username given";
36 7 50       12 }
37 0         0  
38 0         0 if (!$password) {
39             $self->log()->error('No password');
40             die "no password given";
41 7 100       14 }
42 1         22  
43 1         15  
44             $self->log()->debug('verify password for ' . $user );
45              
46             if ($user =~ /[^a-zA-Z0-9_\-\.\@]/) {
47 6         137 $self->log()->error('Invalid chars in username ('.$user.')');
48             return $self->_node_not_exists( $user );
49 6 100       47 }
50 1         25  
51 1         7 my $filename = $self->{LOCATION};
52              
53             if (! -r $filename || ! open FILE, "$filename") {
54 5         8 $self->log()->error('Can\'t open/read from file ' . $filename);
55             die 'Can\'t open/read from file ' . $filename;
56 5 50 33     263 }
57 0         0  
58 0         0 while (<FILE>) {
59             if (/^$user:/) {
60             chomp;
61 5         88 my @t = split(/:/, $_, 3);
62 8 100       104 $self->log()->trace('found line ' . Dumper @t);
63 3         8 #if ($password eq $t[1]) {
64 3         28 if (not defined $t[1]) {
65 3         82 $self->log()->info('Password value not defined for ' . $user);
66             return 0;
67 3 50       154 }
68 0         0  
69 0         0 if (crypt($password, $t[1]) eq $t[1]) {
70             $self->log()->info('Password accepted for ' . $user);
71             return 1;
72 3 100       504 } else {
73 2         51 $self->log()->info('Password mismatch for ' . $user);
74 2         20 return 0;
75             }
76 1         25 }
77 1         12 }
78             return $self->_node_not_exists( $user );
79             }
80              
81 2         13 my $self = shift;
82              
83             # If we have no path, we tell the caller that we are a connector
84             my @path = $self->_build_path( shift );
85 2     2 1 374 if (scalar @path == 0) {
86             return { TYPE => "connector" };
87             }
88 2         7 return {TYPE => "scalar" };
89 2 100       5 }
90 1         8  
91              
92 1         19 my $self = shift;
93              
94             # No path = connector root which always exists
95             my @path = $self->_build_path( shift );
96             if (scalar @path == 0) {
97 4     4 1 7 return 1;
98             }
99              
100 4         12 my $user = shift @path;
101 4 100       14  
102 1         4 my $filename = $self->{LOCATION};
103             if (! -r $filename || ! open FILE, "$filename") {
104             $self->log()->error('Can\'t open/read from file ' . $filename);
105 3         16 return 0;
106             }
107 3         5  
108 3 50 33     153 while (<FILE>) {
109 0         0 if (/^$user:/) {
110 0         0 return 1;
111             }
112             }
113 3         47 return 0;
114 4 100       49 }
115 2         14  
116             no Moose;
117             __PACKAGE__->meta->make_immutable;
118 1         6  
119             1;
120              
121 1     1   7245 =head1 Name
  1         3  
  1         7  
122              
123             Connector::Builtin::Authentication::Password
124              
125             =head1 Description
126              
127             Lightweight connector to check passwords against a unix style password file.
128             Path to the password file is taken from LOCATION.
129              
130             =head2 Usage
131              
132             The username is the first component of the path, the password needs to be
133             passed in the extended parameters using the key password.
134              
135             Example:
136              
137             $connector->get('username', { password => 'mySecret' } );
138              
139             =head2 Return values
140              
141             1 if the password matches, 0 if the user is found but the password does not
142             match and undef if the user is not found.
143              
144             The connector will die if the password file is not readable or if one of
145             the parameters is missing.
146              
147             =head2 Limitations
148              
149             Usernames are limited to [a-zA-Z0-9_\-\.], invalid names are treated as not
150             found.
151