Thanks for the links. I finally stopped getting the following error from the modified filter.
"Error executing class callback in prerun stage: No filters found for 'cpwdmd5' at ...." However, I haven't managed to get the filter to work. Even with the salt fixed, the password stored in the DB (from the test) doesn't *seem* to match. Any suggestions would be appreciated.
package CGI::Application::Plugin::Authentication::Driver::Filter::cpw
+dmd5;
use strict;
use warnings;
sub check {
my $class = shift;
my $param = shift;
my $plain = shift;
my $filtered = shift;
return ( $class->filter( $param, $plain, $filtered ) eq $filtered
+) ? 1 : 0;
}
my $Magic = shift;
my $itoa64 = shift;
$Magic = q/$1$/; # Magic string
$itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstu
+vwxyz";
use Digest::MD5;
sub to64 {
my ($v, $n) = @_;
my $v = shift;
my $n = shift;
my $ret = '';
while (--$n >= 0) {
$ret .= substr($itoa64, $v & 0x3f, 1);
$v >>= 6;
}
$ret;
}
sub apache_md5_crypt {
# change the Magic string to match the one used by Apache
#local $Magic = q/$apr1$/;
unix_md5_crypt(@_);
}
sub filter {
my $ctx = shift;
my $pl = shift;
my $i = shift;
my $ctx1 = shift;
my $pw = shift;
my $passwd = shift;
my $final = shift;
my $pl = shift;
my $i = shift;
my $final =shift;
#sub unix_md5_crypt {
my($pw, $salt) = @_;
my $passwd;
my $salt = ('');
#if ( defined $salt ) {
#$salt =~ s/^\Q$Magic//; # Take care of the magic string if
# if present.
#$salt =~ s/^(.*)\$.*$/$1/; # Salt can have up to 8 chars...
#$salt = substr($salt, 0, 8);
# }
#else {
#$salt = ''; # in case no salt was proffered
#$salt .= substr($itoa64,int(rand(64)+1),1)
#while length($salt) < 8;
# }
$ctx = new Digest::MD5; # Here we start the calculation
$ctx->add($pw); # Original password...
$ctx->add($Magic); # ...our magic string...
$ctx->add($salt); # ...the salt...
my ($final) = new Digest::MD5;
$final->add($pw);
$final->add($salt);
$final->add($pw);
$final = $final->digest;
for ($pl = length($pw); $pl > 0; $pl -= 16) {
$ctx->add(substr($final, 0, $pl > 16 ? 16 : $pl));
}
# Now the 'weird' xform
for ($i = length($pw); $i; $i >>= 1) {
if ($i & 1) { $ctx->add(pack("C", 0)); }
# This comes from the original version,
# where a memset() is done to $final
# before this loop.
else { $ctx->add(substr($pw, 0, 1)); }
}
$final = $ctx->digest;
# The following is supposed to make
# things run slower. In perl, perhaps
# it'll be *really* slow!
for ($i = 0; $i < 1000; $i++) {
$ctx1 = new Digest::MD5;
if ($i & 1) { $ctx1->add($pw); }
else { $ctx1->add(substr($final, 0, 16)); }
if ($i % 3) { $ctx1->add($salt); }
if ($i % 7) { $ctx1->add($pw); }
if ($i & 1) { $ctx1->add(substr($final, 0, 16)); }
else { $ctx1->add($pw); }
$final = $ctx1->digest;
}
# Final xform
$passwd = '';
$passwd .= to64(int(unpack("C", (substr($final, 0, 1))) << 16)
| int(unpack("C", (substr($final, 6, 1))) << 8)
| int(unpack("C", (substr($final, 12, 1)))), 4);
$passwd .= to64(int(unpack("C", (substr($final, 1, 1))) << 16)
| int(unpack("C", (substr($final, 7, 1))) << 8)
| int(unpack("C", (substr($final, 13, 1)))), 4);
$passwd .= to64(int(unpack("C", (substr($final, 2, 1))) << 16)
| int(unpack("C", (substr($final, 8, 1))) << 8)
| int(unpack("C", (substr($final, 14, 1)))), 4);
$passwd .= to64(int(unpack("C", (substr($final, 3, 1))) << 16)
| int(unpack("C", (substr($final, 9, 1))) << 8)
| int(unpack("C", (substr($final, 15, 1)))), 4);
$passwd .= to64(int(unpack("C", (substr($final, 4, 1))) << 16)
| int(unpack("C", (substr($final, 10, 1))) << 8)
| int(unpack("C", (substr($final, 5, 1)))), 4);
$passwd .= to64(int(unpack("C", substr($final, 11, 1))), 2);
$final = '';
return ($Magic . $salt . q/$/ . $passwd);
}
1;
__END__
|