*/ require_once ("domframework/dblayer.php"); /** User authentication against SQL database */ class authsql extends auth { public $dsn = null; public $username = null; public $password = null; 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 informations 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 ("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 ("No SQL table defined", 500); if ($this->fieldIdentifier === null) throw new Exception ("No fieldIdentifier defined", 500); if ($this->fieldPassword === null) throw new Exception ("No fieldPassword defined", 500); $fields = array_merge (array ($this->fieldIdentifier, $this->fieldPassword), $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 ("The SQL database is not connected", 500); $data = $this->db->read (array (array ($this->fieldIdentifier, $email)), array_merge (array ($this->fieldIdentifier, $this->fieldPassword), $this->fieldsInfo)); if (count ($data) === 0) throw new Exception ("Unable to find the user : '$email'", 401); if (! isset ($data[0][$this->fieldPassword])) throw new Exception ("Unable to get the user password from database", 500); $cryptedPassword = $data[0][$this->fieldPassword]; if (crypt ($password, $cryptedPassword) !== $cryptedPassword) throw new Exception ("Bad password for '$email'", 401); unset ($data[0][$this->fieldPassword]); $this->details = $data[0]; } /** 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 ("The SQL database is not connected", 500); if ($this->details === null || ! isset ($this->details[$this->fieldIdentifier])) throw new Exception ( "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_merge (array ($this->fieldIdentifier, $this->fieldPassword), $this->fieldsInfo)); $cryptedPassword = $data[0][$this->fieldPassword]; if (crypt ($oldpassword, $cryptedPassword) !== $cryptedPassword) throw new Exception ("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 ("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 ("The SQL database is not connected", 500); $data = $this->db->read (array (array ($this->fieldIdentifier, $email)), array_merge (array ($this->fieldIdentifier, $this->fieldPassword), $this->fieldsInfo)); if (count ($data) === 0) throw new Exception ("Unable to find the user : '$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 ("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 ("The SQL database is not connected", 500); $data = $this->db->read (null, array_merge (array ($this->fieldIdentifier), $this->fieldsInfo)); return $data; } }