* @license BSD */ //namespace Domframework; require_once ("domframework/dblayer.php"); require_once ("domframework/auth.php"); /** User authentication against SQL database */ class authsql extends auth { /** The DSN to use to connect to SQL database */ public $dsn = null; /** The username to connect to the database */ public $username = null; /** The password to use to connecto to the database */ public $password = null; /** The driver options for the PDO driver */ public $driver_options = null; /** The table name to use */ public $table = null; /** The tableprefix text to prepend to table name (Should finish by _) Just allow chars ! */ public $tableprefix = ""; /** The password field name */ public $fieldPassword = "password"; /** The identifier field name (maybe email) */ public $fieldIdentifier = "email"; /** The field name containing the lastname of the user */ public $fieldLastname = null; /** The field name containing the Firstname of the user */ public $fieldFirstname = null; /** The information fields (in an array) */ public $fieldsInfo = array (); /** The DBLayer pointer */ private $db = null; /** The details of the authenticated user */ private $details = null; /** Establish a connection to a SQL server */ public function connect () { if (! function_exists ("openssl_random_pseudo_bytes")) throw new Exception (dgettext ("domframework", "No PHP support for openssl_random_pseudo_bytes"), 500); $this->db = new dblayer ($this->dsn, $this->username, $this->password, $this->driver_options); if ($this->table === null) throw new Exception (dgettext ("domframework", "No SQL table defined"), 500); if ($this->fieldIdentifier === null) throw new Exception (dgettext ("domframework", "No fieldIdentifier defined"), 500); if ($this->fieldPassword === null) throw new Exception (dgettext ("domframework", "No fieldPassword defined"), 500); if ($this->fieldLastname === null) throw new Exception (dgettext ("domframework", "No fieldLastname defined"), 500); if ($this->fieldFirstname === null) throw new Exception (dgettext ("domframework", "No fieldFirstname defined"), 500); $fields = array_merge (array ($this->fieldIdentifier, $this->fieldPassword, $this->fieldLastname, $this->fieldFirstname), $this->fieldsInfo); $fields = array_flip ($fields); foreach ($fields as $key=>$val) $fields[$key] = array ("varchar", "255"); $this->db->table = $this->table; $this->db->fields = $fields; $this->db->primary = $this->fieldIdentifier; } /** 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) { if ($this->db === null) throw new Exception (dgettext ("domframework", "The SQL database is not connected"), 500); $data = $this->db->read (array (array ($this->fieldIdentifier, $email)), array_merge (array ($this->fieldIdentifier, $this->fieldFirstname, $this->fieldLastname, $this->fieldPassword), $this->fieldsInfo)); if (count ($data) === 0) throw new Exception (sprintf (dgettext ("domframework", "Unable to find the user : '%s'"), $email), 401); if (! isset ($data[0][$this->fieldPassword])) throw new Exception (dgettext ("domframework", "Unable to get the user password from database"), 500); $cryptedPassword = $data[0][$this->fieldPassword]; if (crypt ($password, $cryptedPassword) !== $cryptedPassword) throw new Exception (sprintf (dgettext ("domframework", "Bad password for '%s'"), $email), 401); // The password should never be stored by this function unset ($data[0][$this->fieldPassword]); $content = $data[0]; $content["email"] = $data[0][$this->fieldIdentifier]; $content["lastname"] = $data[0][$this->fieldLastname]; $content["firstname"] = $data[0][$this->fieldFirstname]; $this->details = $content; } /** Return all the parameters recorded for the authenticate user */ public function getdetails () { return $this->details; } /** 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) { if ($this->db === null) throw new Exception (dgettext ("domframework", "The SQL database is not connected"), 500); if ($this->details === null || ! isset ($this->details[$this->fieldIdentifier])) throw new Exception (dgettext ("domframework", "Can't change the password if the user is not authenticated"), 500); $data = $this->db->read (array (array ($this->fieldIdentifier, $this->details[$this->fieldIdentifier])), array ($this->fieldIdentifier, $this->fieldPassword)); $cryptedPassword = $data[0][$this->fieldPassword]; if (crypt ($oldpassword, $cryptedPassword) !== $cryptedPassword) throw new Exception (dgettext ("domframework", "Bad old password provided"), 401); $cost = 11; $salt = substr (base64_encode (openssl_random_pseudo_bytes (17)), 0, 22); $salt = str_replace ("+", ".", $salt); $param = '$'.implode('$', array( "2y", //select the most secure version of blowfish (>=PHP 5.3.7) str_pad ($cost, 2, "0", STR_PAD_LEFT), //add the cost in two digits $salt //add the salt )); //now do the actual hashing $cryptpassword = crypt ($newpassword, $param); $rc = $this->db->update ($this->details[$this->fieldIdentifier], array ($this->fieldPassword => $cryptpassword)); if ($rc !== 1) throw new Exception (dgettext ("domframework", "Can't change the password"), 500); } /** 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) { if ($this->db === null) throw new Exception (dgettext ("domframework", "The SQL database is not connected"), 500); $data = $this->db->read (array (array ($this->fieldIdentifier, $email)), array ($this->fieldIdentifier, $this->fieldPassword)); if (count ($data) === 0) throw new Exception (sprintf (dgettext ("domframework", "Unable to find the user : '%s'"), $email), 401); $cost = 11; $salt = substr (base64_encode (openssl_random_pseudo_bytes (17)), 0, 22); $salt = str_replace ("+", ".", $salt); $param = '$'. implode ('$', array ( "2y", //select the most secure version of blowfish (>=PHP 5.3.7) str_pad ($cost, 2, "0", STR_PAD_LEFT), //add the cost in two digits $salt //add the salt )); //now do the actual hashing $cryptpassword = crypt ($newpassword, $param); $rc = $this->db->update ($email, array ($this->fieldPassword => $cryptpassword)); if ($rc !== 1) throw new Exception (dgettext ("domframework", "Can't change the password"), 500); } /** List all the users available in the database Return firstname, lastname, mail, with mail is an array */ public function listusers () { if ($this->db === null) throw new Exception (dgettext ("domframework", "The SQL database is not connected"), 500); $data = $this->db->read (null, array_merge (array ($this->fieldIdentifier, $this->fieldFirstname, $this->fieldLastname), $this->fieldsInfo)); return $data; } }