File Coverage

blib/lib/App/Unix/RPasswd/SaltedPasswd.pm
Criterion Covered Total %
statement 41 41 100.0
branch 2 2 100.0
condition n/a
subroutine 7 7 100.0
pod 0 1 0.0
total 50 51 98.0


line stmt bran cond sub pod time code
1             package App::Unix::RPasswd::SaltedPasswd;
2             # This is an internal module of App::Unix::RPasswd
3              
4 3     3   21219 use feature ':5.10';
  3         9  
  3         348  
5 3     3   886 use Moo;
  3         23445  
  3         29  
6 3     3   4830 use Crypt::PasswdMD5 ('unix_md5_crypt');
  3         3310  
  3         177  
7 3     3   2735 use List::MoreUtils ('zip');
  3         3694  
  3         1826  
8              
9             our $VERSION = '0.53';
10             our $AUTHOR = 'Claudio Ramirez ';
11              
12             has 'salt' => (
13             is => 'ro',
14             #isa => 'Str',
15             required => 1,
16             );
17              
18             has 'minalpha' => ( # Minimum number of alpha character required
19             is => 'ro',
20             #isa => 'Int',
21             default => sub { 2 }, # 2 is the default in Solaris 11
22             required => 0,
23             );
24              
25             sub generate {
26 3     3 0 1385 my ($self, $base_password) = @_;
27            
28             # Create an encoded string
29 3         22 my $passwd = $self->_encode_string(
30             unix_md5_crypt( $base_password, $self->salt ) );
31            
32             # If necessary convert it to respect the minalpha constraint
33 3         18 $passwd = $self->_minalpha_conv($passwd);
34 3         19 return $passwd;
35             }
36              
37             sub _encode_string {
38 3     3   53087 my ( $self, $opasswd ) = @_;
39 3         11 $opasswd =~ tr/ /./;
40 3         22 $opasswd =~ s/\$//g;
41 3         39 my @array1 = split( //, $opasswd );
42 3         30 my @array2 = reverse @array1;
43 3         83 my @array3 = zip( @array2, @array1 );
44 3         22 my $npasswd = join( '', @array3 );
45 3         12 my $offset = ( length $npasswd ) / 2 + 3;
46 3         7 my $passwd = substr( $npasswd, $offset, 12 ); # The password is 12 chars long
47 3         33 return reverse $passwd;
48             }
49              
50             sub _minalpha_conv {
51 5     5   11 my ( $self, $opasswd ) = @_;
52 5         8 my $passwd;
53 5         11 my $first8_chars = substr($opasswd, 0, 8);
54 5 100       28 if ($first8_chars !~ /[0-9]/) {
55 2         6 my $ascii_value = ord(substr($first8_chars, 0, 1));
56 2         4 my $sum;
57 2         15 do {
58 3         10 $sum = 0;
59 3         13 my @digits = split(//,$ascii_value);
60 3         10 for my $d (@digits) { $sum += $d; }
  7         18  
61 3         18 $ascii_value = $sum;
62             } while (length $sum != 1);
63 2         7 $passwd = $sum . substr($opasswd, 1);
64             }
65 3         6 else { $passwd = $opasswd; }
66 5         17 return $passwd;
67             }
68              
69             1;
70              
71             # Additional properties of generated passwords
72             #MINDIFF=3 Minimum differences required between an old and a new password => OK (statically)
73             #MINALPHA=2 Minimum number of alpha character required => Done
74              
75             # MAYBE TODO: make passwords suitable for new default configurations (e.g. Solaris 11)
76             #MINNONALPHA=1 Minimum number of non-alpha (including numeric and special) required
77             #MINUPPER=0 Minimum number of upper case letters tequired
78             #MINLOWER=0 Minimum number of lower case letters required
79             #MAXREPEATS=0 Maximum number of allowable consecutive repeating characters
80             #MINSPECIAL=0 Minimum number of special (non-alpha and non-digit) characters required
81             #MINDIGIT=0 Minimum number of digits required
82             #WHITESPACE=YES Determine if white space characters are allowed in passwords