|
|
package NGCP::BulkProcessor::RandomString;
|
|
|
use strict;
|
|
|
|
|
|
## no critic
|
|
|
|
|
|
require Exporter;
|
|
|
our @ISA = qw(Exporter);
|
|
|
our @EXPORT_OK = qw(
|
|
|
check_passwordstring
|
|
|
createsalt
|
|
|
createpassworddummy
|
|
|
createtmpstring
|
|
|
|
|
|
$passwordokmessage
|
|
|
$passwordtooshortviolationmessage
|
|
|
$passwordtoolongviolationmessage
|
|
|
$passwordinvalidcharfoundviolationmessage
|
|
|
$passwordcharacterminoccurenceviolationmessage
|
|
|
$passwordcharactermaxoccurenceviolationmessage
|
|
|
|
|
|
$smallletterscharacterclass
|
|
|
$capitalletterscharacterclass
|
|
|
$digitscharacterclass
|
|
|
$umlautscharacterclass
|
|
|
$altsymbolscharacterclass
|
|
|
$symbolscharacterclass
|
|
|
|
|
|
$characterclasses
|
|
|
);
|
|
|
|
|
|
our $maxpasswordlength = 30;
|
|
|
#our $maxpasswordfieldsize = 36;
|
|
|
our $minpasswordlength = 6;
|
|
|
our $saltlength = 8;
|
|
|
our $passworddummylength = 8;
|
|
|
|
|
|
our $smallletterscharacterclass = 1;
|
|
|
our $capitalletterscharacterclass = 2;
|
|
|
our $digitscharacterclass = 3;
|
|
|
our $umlautscharacterclass = 4;
|
|
|
our $altsymbolscharacterclass = 5;
|
|
|
our $symbolscharacterclass = 6;
|
|
|
|
|
|
our $characterclasses = { $smallletterscharacterclass => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'],
|
|
|
$capitalletterscharacterclass => ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
|
|
|
$digitscharacterclass => ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
|
|
$umlautscharacterclass => ['<27>', '<27>', '<27>', '<27>', '<27>', '<27>', '<27>'],
|
|
|
$altsymbolscharacterclass => ['<27>','<27>','@','~'],
|
|
|
$symbolscharacterclass => ['^','<27>','!','"','<27>','$','%','&','/','{','(','[',']',')','}','=','?','\\','<27>','`','+','*','-','#','\'','-','_','.',':',';','|','<','>']
|
|
|
};
|
|
|
|
|
|
my $passworddummycharacterset = [$smallletterscharacterclass,$digitscharacterclass];
|
|
|
my $passwordcharacterset = [$smallletterscharacterclass,$capitalletterscharacterclass,$digitscharacterclass,$umlautscharacterclass,$altsymbolscharacterclass,$symbolscharacterclass];
|
|
|
my $saltcharacterset = [$smallletterscharacterclass,$capitalletterscharacterclass,$digitscharacterclass];
|
|
|
my $tmpcharacterset = [$capitalletterscharacterclass,$digitscharacterclass];
|
|
|
|
|
|
my $passworddummycharacterminoccurences = {
|
|
|
$smallletterscharacterclass => 0,
|
|
|
$digitscharacterclass => 0};
|
|
|
my $passworddummycharactermaxoccurences = {
|
|
|
$smallletterscharacterclass => $maxpasswordlength,
|
|
|
$digitscharacterclass => $maxpasswordlength};
|
|
|
my $passwordcharacterminoccurences = {
|
|
|
$smallletterscharacterclass => 0,
|
|
|
$capitalletterscharacterclass => 0,
|
|
|
$digitscharacterclass => 0,
|
|
|
$umlautscharacterclass => 0,
|
|
|
$altsymbolscharacterclass => 0,
|
|
|
$symbolscharacterclass => 0};
|
|
|
my $passwordcharactermaxoccurences = {
|
|
|
$smallletterscharacterclass => $maxpasswordlength,
|
|
|
$capitalletterscharacterclass => $maxpasswordlength,
|
|
|
$digitscharacterclass => $maxpasswordlength,
|
|
|
$umlautscharacterclass => $maxpasswordlength,
|
|
|
$altsymbolscharacterclass => $maxpasswordlength,
|
|
|
$symbolscharacterclass => $maxpasswordlength};
|
|
|
my $saltcharacterminoccurences = {
|
|
|
$smallletterscharacterclass => 2,
|
|
|
$capitalletterscharacterclass => 2,
|
|
|
$digitscharacterclass => 2};
|
|
|
my $saltcharactermaxoccurences = {
|
|
|
$smallletterscharacterclass => $saltlength,
|
|
|
$capitalletterscharacterclass => $saltlength,
|
|
|
$digitscharacterclass => $saltlength};
|
|
|
my $tmpcharacterminoccurences = {};
|
|
|
my $tmpcharactermaxoccurences = {};
|
|
|
|
|
|
our $passwordokmessage = 1;
|
|
|
our $passwordtooshortviolationmessage = -1;
|
|
|
our $passwordtoolongviolationmessage = -2;
|
|
|
our $passwordinvalidcharfoundviolationmessage = -3;
|
|
|
our $passwordcharacterminoccurenceviolationmessage = -4;
|
|
|
my $passwordcharacterminoccurenceviolationmessages = {
|
|
|
$smallletterscharacterclass => 'PasswordCharacterMinOccurenceViolation1Message',
|
|
|
$capitalletterscharacterclass => 'PasswordCharacterMinOccurenceViolation2Message',
|
|
|
$digitscharacterclass => 'PasswordCharacterMinOccurenceViolation3Message',
|
|
|
$umlautscharacterclass => 'PasswordCharacterMinOccurenceViolation4Message',
|
|
|
$altsymbolscharacterclass => 'PasswordCharacterMinOccurenceViolation5Message',
|
|
|
$symbolscharacterclass => 'PasswordCharacterMinOccurenceViolation6Message'};
|
|
|
our $passwordcharactermaxoccurenceviolationmessage = -5;
|
|
|
my $passwordcharactermaxoccurenceviolationmessages = {
|
|
|
$smallletterscharacterclass => 'PasswordCharacterMaxOccurenceViolation1Message',
|
|
|
$capitalletterscharacterclass => 'PasswordCharacterMaxOccurenceViolation2Message',
|
|
|
$digitscharacterclass => 'PasswordCharacterMaxOccurenceViolation3Message',
|
|
|
$umlautscharacterclass => 'PasswordCharacterMaxOccurenceViolation4Message',
|
|
|
$altsymbolscharacterclass => 'PasswordCharacterMaxOccurenceViolation5Message',
|
|
|
$symbolscharacterclass => 'PasswordCharacterMaxOccurenceViolation6Message'};
|
|
|
my $passwordviolationmessages = {
|
|
|
$passwordokmessage => 'PasswordOKMessage',
|
|
|
$passwordtooshortviolationmessage => 'PasswordTooShortViolationMessage',
|
|
|
$passwordtoolongviolationmessage => 'PasswordTooLongViolationMessage',
|
|
|
$passwordinvalidcharfoundviolationmessage => 'PasswordInvalidCharFoundViolationMessage',
|
|
|
$passwordcharacterminoccurenceviolationmessage => '',
|
|
|
$passwordcharactermaxoccurenceviolationmessage => ''};
|
|
|
|
|
|
sub randstring {
|
|
|
|
|
|
my ($lengthofstring,$characterclasses_ref,$characterset_ref,$minoccurences_ref,$maxoccurences_ref) = @_;
|
|
|
|
|
|
my $output = '';
|
|
|
|
|
|
if ($lengthofstring > 0) {
|
|
|
|
|
|
my %classesusedcount = ();
|
|
|
my %classesrequiredcount = ();
|
|
|
my $classesrequiredcountsum = 0;
|
|
|
|
|
|
my @characterset = @$characterset_ref;
|
|
|
|
|
|
foreach my $characterclassid (@characterset) {
|
|
|
|
|
|
if (exists $minoccurences_ref->{$characterclassid}) {
|
|
|
$classesrequiredcount{$characterclassid} = $minoccurences_ref->{$characterclassid};
|
|
|
$classesrequiredcountsum += $minoccurences_ref->{$characterclassid};
|
|
|
} else {
|
|
|
$classesrequiredcount{$characterclassid} = 0;
|
|
|
}
|
|
|
$classesusedcount{$characterclassid} = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
for (my $i = 0; $i < $lengthofstring; $i += 1) {
|
|
|
|
|
|
my %availablerandcharacters = ();
|
|
|
my @currentcharacterset = ();
|
|
|
my $charactersleft = $lengthofstring - $i;
|
|
|
|
|
|
foreach my $characterclassid (@characterset) {
|
|
|
|
|
|
if ($classesrequiredcountsum >= $charactersleft) {
|
|
|
if (exists $minoccurences_ref->{$characterclassid} and
|
|
|
$classesrequiredcount{$characterclassid} > 0) {
|
|
|
|
|
|
my @characters = @{$characterclasses_ref->{$characterclassid}};
|
|
|
my $characterindex = int(rand($#characters + 1) + 1);
|
|
|
$availablerandcharacters{$characterclassid} = $characters[$characterindex - 1];
|
|
|
push @currentcharacterset,$characterclassid;
|
|
|
|
|
|
}
|
|
|
} else {
|
|
|
if ((!exists $maxoccurences_ref->{$characterclassid}) or
|
|
|
(exists $maxoccurences_ref->{$characterclassid} and
|
|
|
$classesusedcount{$characterclassid} < $maxoccurences_ref->{$characterclassid})) {
|
|
|
|
|
|
my @characters = @{$characterclasses_ref->{$characterclassid}};
|
|
|
my $characterindex = int(rand($#characters + 1) + 1);
|
|
|
$availablerandcharacters{$characterclassid} = $characters[$characterindex - 1];
|
|
|
push @currentcharacterset,$characterclassid;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
my $charactersetclassindex = int(rand(scalar @currentcharacterset) + 1);
|
|
|
my $characterclassid = $currentcharacterset[$charactersetclassindex - 1];
|
|
|
$classesrequiredcount{$characterclassid}--;
|
|
|
if (exists $minoccurences_ref->{$characterclassid}) {
|
|
|
$classesrequiredcountsum--;
|
|
|
}
|
|
|
|
|
|
$classesusedcount{$characterclassid}++;
|
|
|
|
|
|
$output .= $availablerandcharacters{$characterclassid};
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
}
|
|
|
|
|
|
sub check_passwordstring {
|
|
|
|
|
|
my ($password) = @_;
|
|
|
|
|
|
if (length($password) < $minpasswordlength) {
|
|
|
return ($passwordtooshortviolationmessage,
|
|
|
$passwordviolationmessages->{$passwordtooshortviolationmessage});
|
|
|
} elsif (length($password) > $maxpasswordlength) {
|
|
|
return ($passwordtoolongviolationmessage,
|
|
|
$passwordviolationmessages->{$passwordtoolongviolationmessage});
|
|
|
}
|
|
|
|
|
|
my $validcharcount = 0;
|
|
|
|
|
|
foreach my $characterclassid (@$passwordcharacterset) {
|
|
|
|
|
|
my @characters = @{$characterclasses->{$characterclassid}};
|
|
|
my $occurencecount = 0;
|
|
|
|
|
|
foreach my $character (@characters) {
|
|
|
$occurencecount += _substringoccurence($password,$character);
|
|
|
}
|
|
|
|
|
|
$validcharcount += $occurencecount;
|
|
|
|
|
|
if (exists $passwordcharacterminoccurences->{$characterclassid} and
|
|
|
$occurencecount < $passwordcharacterminoccurences->{$characterclassid}) {
|
|
|
return ($passwordcharacterminoccurenceviolationmessage,
|
|
|
$passwordcharacterminoccurenceviolationmessages->{$characterclassid});
|
|
|
} elsif (exists $passwordcharactermaxoccurences->{$characterclassid} and
|
|
|
$occurencecount > $passwordcharactermaxoccurences->{$characterclassid}) {
|
|
|
return ($passwordcharactermaxoccurenceviolationmessage,
|
|
|
$passwordcharactermaxoccurenceviolationmessages->{$characterclassid});
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($validcharcount < length($password)) {
|
|
|
return ($passwordinvalidcharfoundviolationmessage,
|
|
|
$passwordviolationmessages->{$passwordinvalidcharfoundviolationmessage});
|
|
|
}
|
|
|
|
|
|
return ($passwordokmessage,
|
|
|
$passwordviolationmessages->{$passwordokmessage});
|
|
|
|
|
|
}
|
|
|
|
|
|
sub _substringoccurence {
|
|
|
my ($inputstring,$substring) = @_;
|
|
|
my $result = 0;
|
|
|
my $position = 0;
|
|
|
my $posincrement = length($substring);
|
|
|
if ($posincrement > 0) {
|
|
|
do {
|
|
|
$position = index($inputstring,$substring,$position);
|
|
|
if ($position >= 0) {
|
|
|
$result += 1;
|
|
|
$position += $posincrement;
|
|
|
}
|
|
|
} while ($position >= 0);
|
|
|
}
|
|
|
return $result;
|
|
|
}
|
|
|
|
|
|
sub createsalt {
|
|
|
|
|
|
return randstring($saltlength,
|
|
|
$characterclasses,
|
|
|
$saltcharacterset,
|
|
|
$saltcharacterminoccurences,
|
|
|
$saltcharactermaxoccurences);
|
|
|
|
|
|
}
|
|
|
|
|
|
sub createpassworddummy {
|
|
|
|
|
|
return randstring($passworddummylength,
|
|
|
$characterclasses,
|
|
|
$passworddummycharacterset,
|
|
|
$passworddummycharacterminoccurences,
|
|
|
$passworddummycharactermaxoccurences);
|
|
|
|
|
|
}
|
|
|
|
|
|
sub createtmpstring {
|
|
|
|
|
|
my $lengthofstring = shift;
|
|
|
return randstring($lengthofstring,
|
|
|
$characterclasses,
|
|
|
$tmpcharacterset,
|
|
|
$tmpcharacterminoccurences,
|
|
|
$tmpcharactermaxoccurences);
|
|
|
|
|
|
}
|
|
|
|
|
|
1;
|