From f4cc782bb1ff3f0c0479999547e7146452d11c33 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Sun, 4 Aug 2013 19:51:09 +0300 Subject: [PATCH 1/1] Initial commit --- Changes | 4 + MANIFEST | 6 ++ Makefile.PL | 18 ++++ README | 31 ++++++ lib/Apache2/Authen/Passphrase.pm | 162 +++++++++++++++++++++++++++++++ lib/Apache2/Authen/pod2htmd.tmp | 2 + lib/Apache2/Authen/pod2htmi.tmp | 2 + t/Apache2-Authen-Passphrase.t | 34 +++++++ 8 files changed, 259 insertions(+) create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 Makefile.PL create mode 100644 README create mode 100644 lib/Apache2/Authen/Passphrase.pm create mode 100644 lib/Apache2/Authen/pod2htmd.tmp create mode 100644 lib/Apache2/Authen/pod2htmi.tmp create mode 100644 t/Apache2-Authen-Passphrase.t diff --git a/Changes b/Changes new file mode 100644 index 0000000..ca77758 --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for Perl extension Apache2::Authen::Passphrase. + +0.001 Sun 4 Aug 19:47:54 EEST 2013 + - Initial Release diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..757c281 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,6 @@ +Changes +Makefile.PL +MANIFEST +README +t/Apache2-Authen-Passphrase.t +lib/Apache2/Authen/Passphrase.pm diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..bb06469 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,18 @@ +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Apache2::Authen::Passphrase', + VERSION_FROM => 'lib/Apache2/Authen/Passphrase.pm', + ABSTRACT_FROM => 'lib/Apache2/Authen/Passphrase.pm', + AUTHOR => 'Marius Gavrilescu ', + MIN_PERL_VERSION => '5.14.0', + LICENSE => 'perl', + PREREQ_PM => { + Apache2::RequestRec => 0, + Apache2::Access => 0, + Apache2::Const => 0, + Authen::Passphrase => 0, + Authen::Passphrase::BlowfishCrypt => 0, + YAML::Any => 0, + }, +); diff --git a/README b/README new file mode 100644 index 0000000..1149eeb --- /dev/null +++ b/README @@ -0,0 +1,31 @@ +Apache2-Authen-Passphrase version 0.001 +======================================= + +Apache2::Authen::Passphrase is a perl module which provides easy-to-use Apache2 authentication. It exports some utility functions and it contains a PerlAuthenHandler. + +Please read the Apache2::Authen::Passphrase POD for detailed information. + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + +* mod_perl2 +* Authen::Passphrase +* YAML::Any + +COPYRIGHT AND LICENCE + +Copyright (C) 2013 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.14.2 or, +at your option, any later version of Perl 5 you may have available. diff --git a/lib/Apache2/Authen/Passphrase.pm b/lib/Apache2/Authen/Passphrase.pm new file mode 100644 index 0000000..0770f74 --- /dev/null +++ b/lib/Apache2/Authen/Passphrase.pm @@ -0,0 +1,162 @@ +package Apache2::Authen::Passphrase 0.001; + +use 5.014000; +use strict; +use warnings; +use parent qw/Exporter/; + +use constant +{ + USER_REGEX => qr/^\w{2,20}$/pa, + PASSPHRASE_VERSION => 1, + INVALID_USER => "invalid-user\n", + BAD_PASSWORD => "bad-password\n", +}; + +use Apache2::RequestRec; +use Apache2::Access; +use Apache2::Const qw/OK HTTP_UNAUTHORIZED/; +use Authen::Passphrase; +use Authen::Passphrase::BlowfishCrypt; +use YAML::Any qw/LoadFile DumpFile/; + +our @EXPORT_OK = qw/pwset pwcheck pwhash USER_REGEX PASSPHRASE_VERSION INVALID_USER BAD_PASSWORD/; + +################################################## + +our $rootdir; + +sub pwhash{ + my ($pass)=@_; + + my $ppr=Authen::Passphrase::BlowfishCrypt->new( + cost => 10, + passphrase => $pass, + salt_random => 1, + ); + + $ppr->as_rfc2307 +} + +sub pwset{ + my ($user, $pass)=@_; + + my $file = "$rootdir/us/$user.yml"; + my $conf = eval { LoadFile $file } // undef; + $conf->{passphrase}=pwhash $pass; + $conf->{passphrase_version}=PASSPHRASE_VERSION; + DumpFile $file, $conf; + + chmod 0660, $file; +} + +sub pwcheck{ + my ($user, $pass)=@_; + die INVALID_USER unless $user =~ USER_REGEX; + $user=${^MATCH};# Make taint shut up + my $conf=LoadFile "$rootdir/us/$user.yml"; + + die BAD_PASSWORD unless keys $conf;# Empty hash means no such user + die BAD_PASSWORD unless Authen::Passphrase->from_rfc2307($conf->{passphrase})->match($pass); + pwset $user, $pass if $conf->{passphrase_version} < PASSPHRASE_VERSION +} + +sub handler{ + my $r=shift; + + my ($rc, $pass) = $r->get_basic_auth_pw; + return $rc unless $rc == OK; + + my $user=$r->user; + unless (eval { pwcheck $user, $pass; 1 }) { + $r->note_basic_auth_failure; + return HTTP_UNAUTHORIZED + } + + OK +} + +1; +__END__ + +=head1 NAME + +Apache2::Authen::Passphrase - basic authentication with Authen::Passphrase + +=head1 SYNOPSIS + + use Apache2::Authen::Passphrase qw/pwcheck pwset pwhash/; + my $hash = pwhash $username, $password; + pwset $username, "pass123"; + eval { pwcheck $username, "pass123" }; + + # In Apache2 config + + PerlAuthenHandler Apache2::Authen::Passphrase + AuthName MyAuth + Require valid-user + + +=head1 DESCRIPTION + +Apache2::Authen::Passphrase is a perl module which provides easy-to-use Apache2 authentication. It exports some utility functions and it contains a PerlAuthenHandler. + +=head1 FUNCTIONS + +=over + +=item B() + +Takes the password as a single argument and returns the password hash. + +=item B(I<$username>, I<$password>) + +Sets the password of $username to $password. + +=item B(I<$username>, I<$password>) + +Checks the given username and password, throwing an exception if the username is invalid or the password is incorrect. + +=item B + +The PerlAuthenHandler for use in apache2. It uses Basic Access Authentication. + +=item B + +A regex that matches valid usernames. Usernames must be at least 2 characters, at most 20 characters, and they may only contain word characters (C<[A-Za-z0-9_]>). + +=item B + +Exception thrown if the username does not match C. + +=item B + +Exception thrown if the password is different from the one stored in the user's yml file. + +=item B + +The version of the passphrase. It is incremented each time the passphrase hashing scheme is changed. Versions so far: + +=over + +=item Version 1 B<(current)> + +Uses C with a cost factor of 10 + +=back + +=back + +=head1 AUTHOR + +Marius Gavrilescu, Emarius@ieval.roE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2013 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.14.2 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/lib/Apache2/Authen/pod2htmd.tmp b/lib/Apache2/Authen/pod2htmd.tmp new file mode 100644 index 0000000..61e86d9 --- /dev/null +++ b/lib/Apache2/Authen/pod2htmd.tmp @@ -0,0 +1,2 @@ + +. diff --git a/lib/Apache2/Authen/pod2htmi.tmp b/lib/Apache2/Authen/pod2htmi.tmp new file mode 100644 index 0000000..61e86d9 --- /dev/null +++ b/lib/Apache2/Authen/pod2htmi.tmp @@ -0,0 +1,2 @@ + +. diff --git a/t/Apache2-Authen-Passphrase.t b/t/Apache2-Authen-Passphrase.t new file mode 100644 index 0000000..b27498b --- /dev/null +++ b/t/Apache2-Authen-Passphrase.t @@ -0,0 +1,34 @@ +use v5.14; +use strict; +use warnings; + +use File::Temp qw/tempdir/; +use Test::More tests => 7; +BEGIN { use_ok('Apache2::Authen::Passphrase', qw/pwset pwcheck/) }; + +my $tempdir = tempdir CLEANUP => 1; +mkdir "$tempdir/us"; +$Apache2::Authen::Passphrase::rootdir = $tempdir; + +sub pw_ok { + my ($user, $pass, $testname) = @_; + eval { pwcheck $user, $pass }; + is $@, '', $testname; +} + +sub pw_nok { + my ($user, $pass, $testname) = @_; + eval { pwcheck $user, $pass }; + isnt $@, '', $testname; +} + +pwset marius => 'password'; +pw_ok marius => 'password', 'Set password and check it'; +pw_nok marius => 'anotherpassword', 'Check an incorrect password'; + +pwset marius => 'anotherpassword'; +pw_ok marius => 'anotherpassword', 'Change the password and check it'; + +pw_nok 'BadUsername++', 'a', 'Bad username'; +pw_nok 'a', 'a', 'Short username'; +pw_nok 'asfwe0g3girg4ih45jho45ih45hi45h045jh4oh', 'a', 'Long username'; -- 2.39.2