<?php namespace HashOver; // Copyright (C) 2015-2019 Jacob Barkdull // This file is part of HashOver. // // HashOver is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // HashOver is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with HashOver. If not, see <http://www.gnu.org/licenses/>. class Login extends Secrets { protected $setup; protected $cookies; protected $formData; protected $locale; protected $crypto; protected $loginMethod; protected $fieldNeeded; public $name; public $password; public $loginHash; public $email; public $website; public $userIsLoggedIn = false; public $userIsAdmin = false; public function __construct (Setup $setup) { // Store parameters as properties $this->setup = $setup; // Instantiate various classes $this->cookies = new Cookies ($setup, $this); $this->formData = new FormData ($setup, $this->cookies); $this->locale = new Locale ($setup); $this->crypto = new Crypto (); // Name of login method class to instantiate $login_class = 'HashOver\\' . $setup->loginMethod; // Instantiate login method class $this->loginMethod = new $login_class ($setup, $this->cookies, $this->locale); // Error message to display to the user $this->fieldNeeded = $this->locale->text['field-needed']; // Check if user is logged in $this->getLogin (); } // Prepares login credentials public function prepareCredentials () { // Set name if (isset ($this->formData->data['name'])) { $this->loginMethod->name = $this->formData->data['name']; } // Attempt to get name $name = $this->setup->getRequest ('name'); // Attempt to get password $password = $this->setup->getRequest ('password'); // Set password if ($password !== false) { $this->loginMethod->password = $this->crypto->createHash ($password); } else { $this->loginMethod->password = ''; } // Check if login hash is not set if ($this->loginHash === null) { // If so, generate a random password $random_password = bin2hex (openssl_random_pseudo_bytes (16)); // And use user password or random password $password = $password ?: $random_password; } // Generate a RIPEMD-160 hash to indicate user login $this->loginMethod->loginHash = hash ('ripemd160', $name . $password); // Set e-mail address if (isset ($this->formData->data['email'])) { $this->loginMethod->email = $this->formData->data['email']; } // Set website URL if (isset ($this->formData->data['website'])) { $this->loginMethod->website = $this->formData->data['website']; } } // Update login credentials public function updateCredentials () { $this->name = $this->loginMethod->name; $this->password = $this->loginMethod->password; $this->loginHash = $this->loginMethod->loginHash; $this->email = $this->loginMethod->email; $this->website = $this->loginMethod->website; // Validate e-mail address if (!empty ($this->email)) { if (!filter_var ($this->email, FILTER_VALIDATE_EMAIL)) { $this->email = ''; } } // Prepend "http://" to website URL if missing if (!empty ($this->website)) { if (!preg_match ('/htt(p|ps):\/\//i', $this->website)) { $this->website = 'http://' . $this->website; } } } // Set login credentials public function setCredentials () { // Prepare login credentials $this->prepareCredentials (); // Set login method credentials $this->loginMethod->setCredentials (); // Update login credentials $this->updateCredentials (); } // Get login method credentials public function getCredentials () { $this->loginMethod->getCredentials (); $this->updateCredentials (); } // Checks if required fields have values public function validateFields () { // Run through login field options foreach ($this->setup->formFields as $field => $status) { // Check if current field is required and is empty if ($status === 'required' and empty ($this->$field)) { // If so, set cookies if request is not AJAX if ($this->formData->viaAJAX !== true) { $this->cookies->setFailedOn ($field, $this->formData->replyTo); } // And throw exception throw new \Exception (sprintf ( $this->fieldNeeded, $this->locale->text[$field] )); } } // Otherwise, fields are valid return true; } // Checks login requirements public function checkRequirements ($message) { // Check if a login is required if ($this->setup->requiresLogin === true) { // If so, throw exception if user is not logged in if ($this->userIsLoggedIn === false) { throw new \Exception ($message); } } // Otherwise, login requirements are met return true; } // Main login method public function setLogin () { // Do nothing if login is disabled if ($this->setup->allowsLogin === false) { return; } // Do nothing if login method is disabled if ($this->loginMethod->enabled === false) { return; } // Otherwise, throw exception if a non-HashOver login is required $this->checkRequirements ('Normal login not allowed!'); // Set login method credentials $this->setCredentials (); // Check if required fields have values $this->validateFields (); // Execute login method's setLogin $this->loginMethod->setLogin (); } // Admin login method public function setAdminLogin () { // Set login method credentials $this->setCredentials (); // Execute login method's setLogin $this->loginMethod->setLogin (); } // Weak verification of an admin login public function isAdmin () { // Create login hash $hash = hash ('ripemd160', $this->adminName . $this->adminPassword); // Check if the hashes match $match = ($this->loginHash === $hash); // And return match return $match; } // Logs user in as admin public function adminLogin () { // Do nothing if login isn't admin if ($this->isAdmin () === false) { return; } // Set e-mail to admin e-mail address $this->loginMethod->email = $this->notificationEmail; // Set website to current domain $this->loginMethod->website = $this->setup->scheme . '://' . $this->setup->domain; // Set login method credentials $this->loginMethod->setCredentials (); // Update login credentials $this->updateCredentials (); // And login method's setLogin $this->loginMethod->setLogin (); } // Strict verification of an admin login public function verifyAdmin ($password = false) { // If no password was given use the current password $password = ($password === false) ? $this->password : $password; // Check if passwords match $match = $this->crypto->verifyHash ($this->adminPassword, $password); // And return match return $match; } // Check if user is logged in public function getLogin () { // Get login method credentials $this->getCredentials (); // Check if user is logged in if (!empty ($this->loginHash)) { // If so, set login indicator $this->userIsLoggedIn = true; // Check if user is logged in as admin if ($this->isAdmin () === true) { $this->userIsAdmin = true; } } } // Main logout method public function clearLogin () { $this->loginMethod->clearLogin (); } }