From 9be561212b04bee396ce688d7908c6f77d412ffb Mon Sep 17 00:00:00 2001 From: Dominique Fournier Date: Sat, 12 Sep 2015 17:08:32 +0000 Subject: [PATCH] authhtpasswd : Add support to authenticate the user from a .htpasswd file, created by "htpasswd" command. Allow to add easily a new user if the admin password is lost git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2279 bf3deb0d-5f1a-0410-827f-c0cc1f45334c --- Tests/authhtpasswdTest.php | 59 ++++++++++++++++++++++++++ authhtpasswd.php | 84 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 Tests/authhtpasswdTest.php create mode 100644 authhtpasswd.php diff --git a/Tests/authhtpasswdTest.php b/Tests/authhtpasswdTest.php new file mode 100644 index 0000000..a45d149 --- /dev/null +++ b/Tests/authhtpasswdTest.php @@ -0,0 +1,59 @@ + */ + +/** Test the authhtpasswd.php file */ +class test_authhtpasswd extends PHPUnit_Framework_TestCase +{ + public function test_clean () + { + @unlink ("/tmp/htpasswd.file"); + file_put_contents ("/tmp/htpasswd.file", + 'toto@toto.com:$2y$05$dO7qyX4simzg3pMgWyqHgeAjFauXEyUdPdyrwDMVNj4fTuE24TGuq' + ."\n". + 'titi@titi.com:$2y$05$dO7qyX4simzg3pMgWyqHgeAjFauXEyUdPdyrwDMVNj4fTuE24TGuq' + ."\n" + ); + } + + public function test_connect () + { + $authhtpasswd = new authhtpasswd (); + $authhtpasswd->htpasswdFile = "/tmp/htpasswd.file"; + $res = $authhtpasswd->connect (); + $this->assertEquals ($res, null); + } + + public function test_authentication1 () + { + $authhtpasswd = new authhtpasswd (); + $authhtpasswd->htpasswdFile = "/tmp/htpasswd.file"; + $res = $authhtpasswd->authentication ("toto@toto.com", "toto123"); + $this->assertEquals ($res, true); + } + + public function test_authentication2 () + { + $authhtpasswd = new authhtpasswd (); + $authhtpasswd->htpasswdFile = "/tmp/htpasswd.file"; + $this->setExpectedException ("Exception"); + $res = $authhtpasswd->authentication ("UNKNOWN@toto.com", "toto123"); + } + + public function test_authentication3 () + { + $authhtpasswd = new authhtpasswd (); + $authhtpasswd->htpasswdFile = "/tmp/htpasswd.file"; + $this->setExpectedException ("Exception"); + $res = $authhtpasswd->authentication ("toto@toto.com", "BAD PASSWD"); + } + + public function test_authentication4 () + { + $authhtpasswd = new authhtpasswd (); + $authhtpasswd->htpasswdFile = "/tmp/htpasswd.file"; + $res = $authhtpasswd->authentication ("titi@titi.com", "toto123"); + $this->assertEquals ($res, true); + } +} diff --git a/authhtpasswd.php b/authhtpasswd.php new file mode 100644 index 0000000..18a6e56 --- /dev/null +++ b/authhtpasswd.php @@ -0,0 +1,84 @@ + */ + +/** User authentication against .htpasswd file + A .htpasswd can be created by the 'htpasswd' command for Apache, and contain + toto@toto.com:$2y$05$uHCUNqicE7Pku3MK1qZaDuJxP/pocqCcEAnacZBjsfWgW9EcuG5y2 + */ +class authhtpasswd extends auth +{ + /** The .htpasswd file to use for authentication */ + public $htpasswdFile; + + public function connect () + { + if (! file_exists ($this->htpasswdFile)) + throw new Exception (sprintf (dgettext("domframework", + "The HTPasswd file '%s' is not found"), + $this->htpasswdFile), 500); + if (! is_readable ($this->htpasswdFile)) + throw new Exception (sprintf (dgettext("domframework", + "The HTPasswd file '%s' is not readable"), + $this->htpasswdFile), 500); + } + + /** Try to authenticate the email/password of the user + @param string $email Email to authenticate + @param string $password Password to authenticate */ + public function authentication ($email, $password) + { + // Redo the checks of connect to not have a property to add + $this->connect (); + $file = file_get_contents ($this->htpasswdFile); + $lines = explode ("\n", $file); + foreach ($lines as $line) + { + // Comment line : skip it + if ($line{0} === "#") + continue; + $line = trim ($line); + $user = strstr ($line, ":", true); + $cryptedPassword = substr (strstr ($line, ':'), 1); + if ($user === $email) + { + if (crypt ($password, $cryptedPassword) !== $cryptedPassword) + throw new Exception ("Bad password for '$email'", 401); + return TRUE; + } + } + throw new Exception ("Unable to find the user : '$email'", 401); + } + + /** Return all the parameters recorded for the authenticate user */ + public function getdetails () + { + throw new Exception (dgettext ("domframework", + "The details can't be provided by HTPasswd file"), + 404); + } + + /** Method to change the password + @param string $oldpassword The old password (to check if the user have the + rights to change the password) + @param string $newpassword The new password to be recorded */ + public function changepassword ($oldpassword, $newpassword) + { + throw new Exception (dgettext("domframework", + "The password can't be change for HTPasswd users"), + 405); + } + + /** Method to overwrite the password (without oldpassword check) + Must be reserved to the administrators. For the users, use changepassword + method + @param string $email the user identifier to select + @param string $newpassword The new password to be recorded */ + public function overwritepassword ($email, $newpassword) + { + throw new Exception (dgettext("domframework", + "The password can't be change for HTPasswd users"), + 405); + } +}