]> git.mxchange.org Git - friendica.git/blobdiff - src/Model/User.php
Merge pull request #4640 from MrPetovan/task/4604-add-password-exposed-check
[friendica.git] / src / Model / User.php
index 7cf7fea2e6562b96f4041326726796750ac98a6f..6270ce9bf3d079462362c3ae600f5e169a5a5f21 100644 (file)
@@ -5,6 +5,7 @@
  */
 namespace Friendica\Model;
 
+use DivineOmega\PasswordExposed\PasswordStatus;
 use Friendica\Core\Addon;
 use Friendica\Core\Config;
 use Friendica\Core\L10n;
@@ -22,6 +23,7 @@ use Friendica\Util\Network;
 use dba;
 use Exception;
 use LightOpenID;
+use function password_exposed;
 
 require_once 'boot.php';
 require_once 'include/dba.php';
@@ -94,56 +96,36 @@ class User
 
 
        /**
-        * @brief Authenticate a user with a clear text password
-        *
-        * User info can be any of the following:
-        * - User DB object
-        * - User Id
-        * - User email or username or nickname
-        * - User array with at least the uid and the hashed password
+        * Authenticate a user with a clear text password
         *
+        * @brief Authenticate a user with a clear text password
         * @param mixed $user_info
         * @param string $password
-        * @return boolean
+        * @return int|boolean
+        * @deprecated since version 3.6
+        * @see User::getIdFromPasswordAuthentication()
         */
        public static function authenticate($user_info, $password)
        {
-               if (is_object($user_info)) {
-                       $user = (array) $user_info;
-               } elseif (is_int($user_info)) {
-                       $user = dba::selectFirst('user', ['uid', 'password', 'legacy_password'],
-                               [
-                                       'uid' => $user_info,
-                                       'blocked' => 0,
-                                       'account_expired' => 0,
-                                       'account_removed' => 0,
-                                       'verified' => 1
-                               ]
-                       );
-               } elseif (is_string($user_info)) {
-                       $user = dba::fetch_first('SELECT `uid`, `password`, `legacy_password`
-                               FROM `user`
-                               WHERE (`email` = ? OR `username` = ? OR `nickname` = ?)
-                               AND `blocked` = 0
-                               AND `account_expired` = 0
-                               AND `account_removed` = 0
-                               AND `verified` = 1
-                               LIMIT 1',
-                               $user_info,
-                               $user_info,
-                               $user_info
-                       );
-               } else {
-                       $user = $user_info;
+               try {
+                       return self::getIdFromPasswordAuthentication($user_info, $password);
+               } catch (Exception $ex) {
+                       return false;
                }
+       }
 
-               if (!DBM::is_result($user)
-                       || !isset($user['uid'])
-                       || !isset($user['password'])
-                       || !isset($user['legacy_password'])
-               ) {
-                       throw new Exception('Not enough information to authenticate');
-               }
+       /**
+        * Returns the user id associated with a successful password authentication
+        *
+        * @brief Authenticate a user with a clear text password
+        * @param mixed $user_info
+        * @param string $password
+        * @return int User Id if authentication is successful
+        * @throws Exception
+        */
+       public static function getIdFromPasswordAuthentication($user_info, $password)
+       {
+               $user = self::getAuthenticationInfo($user_info);
 
                if ($user['legacy_password']) {
                        if (password_verify(self::hashPasswordLegacy($password), $user['password'])) {
@@ -159,7 +141,71 @@ class User
                        return $user['uid'];
                }
 
-               return false;
+               throw new Exception(L10n::t('Login failed'));
+       }
+
+       /**
+        * Returns authentication info from various parameters types
+        *
+        * User info can be any of the following:
+        * - User DB object
+        * - User Id
+        * - User email or username or nickname
+        * - User array with at least the uid and the hashed password
+        *
+        * @param mixed $user_info
+        * @return array
+        * @throws Exception
+        */
+       private static function getAuthenticationInfo($user_info)
+       {
+               $user = null;
+
+               if (is_object($user_info) || is_array($user_info)) {
+                       if (is_object($user_info)) {
+                               $user = (array) $user_info;
+                       } else {
+                               $user = $user_info;
+                       }
+
+                       if (!isset($user['uid'])
+                               || !isset($user['password'])
+                               || !isset($user['legacy_password'])
+                       ) {
+                               throw new Exception(L10n::t('Not enough information to authenticate'));
+                       }
+               } elseif (is_int($user_info) || is_string($user_info)) {
+                       if (is_int($user_info)) {
+                               $user = dba::selectFirst('user', ['uid', 'password', 'legacy_password'],
+                                       [
+                                               'uid' => $user_info,
+                                               'blocked' => 0,
+                                               'account_expired' => 0,
+                                               'account_removed' => 0,
+                                               'verified' => 1
+                                       ]
+                               );
+                       } else {
+                               $user = dba::fetch_first('SELECT `uid`, `password`, `legacy_password`
+                                       FROM `user`
+                                       WHERE (`email` = ? OR `username` = ? OR `nickname` = ?)
+                                       AND `blocked` = 0
+                                       AND `account_expired` = 0
+                                       AND `account_removed` = 0
+                                       AND `verified` = 1
+                                       LIMIT 1',
+                                       $user_info,
+                                       $user_info,
+                                       $user_info
+                               );
+                       }
+
+                       if (!DBM::is_result($user)) {
+                               throw new Exception(L10n::t('User not found'));
+                       }
+               }
+
+               return $user;
        }
 
        /**
@@ -172,6 +218,17 @@ class User
                return autoname(6) . mt_rand(100, 9999);
        }
 
+       /**
+        * Checks if the provided plaintext password has been exposed or not
+        *
+        * @param string $password
+        * @return bool
+        */
+       public static function isPasswordExposed($password)
+       {
+               return password_exposed($password) === PasswordStatus::EXPOSED;
+       }
+
        /**
         * Legacy hashing function, kept for password migration purposes
         *
@@ -477,7 +534,7 @@ class User
                        if ($Image->isValid()) {
                                $Image->scaleToSquare(175);
 
-                               $hash = photo_new_resource();
+                               $hash = Photo::newResource();
 
                                $r = Photo::store($Image, $uid, 0, $hash, $filename, L10n::t('Profile Photos'), 4);