├── resources ├── logs │ └── git.gitkeep ├── classes │ ├── Captcha │ │ ├── Font │ │ │ ├── captcha0.ttf │ │ │ ├── captcha1.ttf │ │ │ ├── captcha2.ttf │ │ │ ├── captcha3.ttf │ │ │ ├── captcha4.ttf │ │ │ └── captcha5.ttf │ │ ├── PhraseBuilderInterface.php │ │ ├── autoload.php │ │ ├── CaptchaBuilderInterface.php │ │ ├── PhraseBuilder.php │ │ └── ImageFileHandler.php │ ├── Config.php │ ├── Logger.php │ ├── PHPMailer │ │ └── PHPMailerAutoload.php │ ├── LoginCheck.php │ ├── FlashMessage.php │ ├── Crypto.php │ ├── ChangeADPassword.php │ ├── Login.php │ ├── UserInfo.php │ ├── ChangePassword.php │ ├── NewLocalAdmin.php │ └── ADLogin.php ├── functions │ ├── sanitize.php │ ├── passwordPolicyMatch.php │ ├── startPDOConnection.php │ ├── sendEmail.php │ ├── ADPasswordPolicyMatch.php │ └── installerFunctions.php ├── templates │ ├── installer_navigation.php │ ├── header.php │ ├── navigation.php │ ├── admin_navigation.php │ ├── not_loggedin_navigation.php │ └── local_navigation.php ├── core │ ├── init.php.sample │ └── structure.sql └── views │ ├── admin_logged_in.php │ ├── local_admin │ ├── not_logged_in.php │ ├── connection_settings.php │ └── usersettings.php │ ├── reset_pw_email.php │ ├── reset_pw.php │ ├── not_logged_in.php │ ├── new_pw.php │ ├── verify_questions.php │ ├── change_pw.php │ └── user_settings.php ├── public ├── css │ ├── ie8.css │ └── styles.css ├── favicon.ico ├── img │ ├── reset.png │ ├── ADReset.png │ └── ADReset_Local.png ├── js │ ├── custom.js │ ├── passwordResetSuccess.js │ ├── invalidCodePrompt.js │ ├── secretQuestionsNotice.js │ ├── localLogoutConfirm.js │ ├── resetSecretQuestionsPrompt.js │ ├── localAdminRequired.js │ ├── resetPrompt.js │ ├── systemSettings.js │ └── bootbox.min.js ├── ajax │ ├── .htaccess │ └── testemailsettings.php ├── resetpw.php ├── changepw.php ├── settings │ ├── localusersettings.php │ ├── connectionsettings.php │ ├── usersettings.php │ └── systemsettings.php ├── account.php ├── localadmin.php ├── userstatus.php ├── resetpwemail.php ├── newpw.php ├── index.php └── verifyquestions.php ├── screenshots ├── 4 New Password.jpg ├── 1 Home - Desktop.jpg ├── 3 Secret Questions.jpg ├── 5 Change Password.jpg ├── 2 Home - Responsive.jpg ├── 6 System Settings 1.jpg └── 7 System Settings 2.jpg ├── docs ├── documentation images │ ├── IIS 01.png │ ├── IIS 02.png │ ├── IIS 03.png │ ├── IIS 04.png │ ├── IIS 05.png │ ├── IIS 06.png │ ├── IIS 07.png │ ├── IIS 08.png │ ├── IIS 09.png │ ├── IIS 10.png │ ├── IIS 11.png │ ├── IIS 12.png │ ├── IIS 13.png │ ├── IIS 14.png │ ├── IIS 15.png │ ├── IIS 16.png │ ├── IIS 17.png │ ├── IIS 18.png │ ├── IIS 19.png │ ├── IIS 20.png │ ├── IIS 21.png │ ├── IIS 22.png │ ├── IIS 23.png │ ├── IIS 24.png │ ├── IIS 25.png │ ├── IIS 26.png │ ├── Installer - 1.png │ ├── Installer - 2.png │ ├── Installer - 3.png │ ├── Installer - 4.png │ ├── Installer - 5.png │ ├── Installer - 6.png │ ├── Certificate - 1.png │ ├── Certificate - 2.png │ ├── Certificate - 3.png │ ├── Certificate - 4.png │ ├── Certificate - 5.png │ ├── Certificate - 6.png │ └── Certificate - 7.png ├── Retrieving the CA Certificate used for LDAPS.md ├── Get-ADResetUserStatus.ps1 └── Windows Server 2012 R2 Installation Guide.md └── README.md /resources/logs/git.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/css/ie8.css: -------------------------------------------------------------------------------- 1 | input { 2 | font-family: Arial; 3 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/img/reset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/public/img/reset.png -------------------------------------------------------------------------------- /public/img/ADReset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/public/img/ADReset.png -------------------------------------------------------------------------------- /public/img/ADReset_Local.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/public/img/ADReset_Local.png -------------------------------------------------------------------------------- /screenshots/4 New Password.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/4 New Password.jpg -------------------------------------------------------------------------------- /screenshots/1 Home - Desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/1 Home - Desktop.jpg -------------------------------------------------------------------------------- /screenshots/3 Secret Questions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/3 Secret Questions.jpg -------------------------------------------------------------------------------- /screenshots/5 Change Password.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/5 Change Password.jpg -------------------------------------------------------------------------------- /docs/documentation images/IIS 01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 01.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 02.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 03.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 04.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 05.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 06.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 07.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 08.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 09.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 10.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 11.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 12.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 13.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 14.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 15.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 16.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 17.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 18.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 19.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 20.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 21.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 22.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 23.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 24.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 25.png -------------------------------------------------------------------------------- /docs/documentation images/IIS 26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/IIS 26.png -------------------------------------------------------------------------------- /screenshots/2 Home - Responsive.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/2 Home - Responsive.jpg -------------------------------------------------------------------------------- /screenshots/6 System Settings 1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/6 System Settings 1.jpg -------------------------------------------------------------------------------- /screenshots/7 System Settings 2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/screenshots/7 System Settings 2.jpg -------------------------------------------------------------------------------- /docs/documentation images/Installer - 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Installer - 1.png -------------------------------------------------------------------------------- /docs/documentation images/Installer - 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Installer - 2.png -------------------------------------------------------------------------------- /docs/documentation images/Installer - 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Installer - 3.png -------------------------------------------------------------------------------- /docs/documentation images/Installer - 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Installer - 4.png -------------------------------------------------------------------------------- /docs/documentation images/Installer - 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Installer - 5.png -------------------------------------------------------------------------------- /docs/documentation images/Installer - 6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Installer - 6.png -------------------------------------------------------------------------------- /resources/classes/Captcha/Font/captcha0.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/resources/classes/Captcha/Font/captcha0.ttf -------------------------------------------------------------------------------- /resources/classes/Captcha/Font/captcha1.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/resources/classes/Captcha/Font/captcha1.ttf -------------------------------------------------------------------------------- /resources/classes/Captcha/Font/captcha2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/resources/classes/Captcha/Font/captcha2.ttf -------------------------------------------------------------------------------- /resources/classes/Captcha/Font/captcha3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/resources/classes/Captcha/Font/captcha3.ttf -------------------------------------------------------------------------------- /resources/classes/Captcha/Font/captcha4.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/resources/classes/Captcha/Font/captcha4.ttf -------------------------------------------------------------------------------- /resources/classes/Captcha/Font/captcha5.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/resources/classes/Captcha/Font/captcha5.ttf -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 1.png -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 2.png -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 3.png -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 4.png -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 5.png -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 6.png -------------------------------------------------------------------------------- /docs/documentation images/Certificate - 7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mprahl/ADReset/HEAD/docs/documentation images/Certificate - 7.png -------------------------------------------------------------------------------- /public/js/custom.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | //For tooltips (help bubbles on hover) 3 | $('[data-toggle="tooltip"]').tooltip(); 4 | }); 5 | -------------------------------------------------------------------------------- /public/js/passwordResetSuccess.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | bootbox.alert("Your password was successfully reset.", function() { 3 | }); 4 | }); -------------------------------------------------------------------------------- /public/ajax/.htaccess: -------------------------------------------------------------------------------- 1 | # This file prevents that your .php view files are accessed directly from the outside 2 | 3 | Require all denied 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/js/invalidCodePrompt.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | bootbox.alert("The reset code you used has expired or is invalid.
Please try resetting your password again.", function() { 3 | }); 4 | }); 5 | -------------------------------------------------------------------------------- /resources/functions/sanitize.php: -------------------------------------------------------------------------------- 1 | Would you like to continue?", function(result) { 4 | if (result) { 5 | window.location.href = "/index.php"; 6 | } 7 | }); 8 | }); 9 | }); -------------------------------------------------------------------------------- /resources/classes/Captcha/PhraseBuilderInterface.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | interface PhraseBuilderInterface 11 | { 12 | /** 13 | * Generates random phrase of given length with given charset 14 | */ 15 | public function build($length, $charset); 16 | 17 | /** 18 | * "Niceize" a code 19 | */ 20 | public function niceize($str); 21 | } 22 | -------------------------------------------------------------------------------- /public/resetpw.php: -------------------------------------------------------------------------------- 1 | = Config::get('security/passwordLength')) { 6 | return true; 7 | } 8 | } 9 | 10 | return false; 11 | } 12 | 13 | function passwordPolicyWritten() { 14 | return 'The password must be ' . Config::get('security/passwordLength') . ' or more characters.'; 15 | } 16 | -------------------------------------------------------------------------------- /public/js/resetSecretQuestionsPrompt.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | $('#resetSecretQuestions input').on('click', function(e){ 3 | bootbox.confirm("Are you sure you want to erase your secret answers? You will have to set your three secret answers again before being able to reset your password using secret questions.", function(result) { 4 | if (result) { 5 | $(e.target).closest("form").submit(); 6 | return true; 7 | } 8 | }); 9 | 10 | return false; 11 | }); 12 | }); -------------------------------------------------------------------------------- /public/js/localAdminRequired.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | $('.connectionSettingsLink').on('click', function() { 3 | bootbox.confirm("Connection Settings must be administered as a local administrator.
Please login as a local administrator from the localadmin.php login form by clicking OK
Please note, you will be logged out of your current session during the process.", function(result) { 4 | if (result) { 5 | window.location.href = "/account.php?logout&page=localadmin.php"; 6 | } 7 | }); 8 | }); 9 | }); -------------------------------------------------------------------------------- /public/changepw.php: -------------------------------------------------------------------------------- 1 | changeFromPOST(); 7 | } 8 | 9 | $builder = new Gregwar\Captcha\CaptchaBuilder; 10 | $builder->setMaxBehindLines(0); 11 | $builder->setMaxFrontLines(0); 12 | $builder->setBackgroundColor(255,255,255); 13 | $builder->build(); 14 | $_SESSION['changepw_captcha'] = $builder->getPhrase(); 15 | 16 | require_once(RESOURCE_DIR . "views/change_pw.php"); 17 | -------------------------------------------------------------------------------- /public/settings/localusersettings.php: -------------------------------------------------------------------------------- 1 | setProfile($_SESSION['user_name']); 10 | } 11 | 12 | if (LoginCheck::isLoggedInAsAdmin()) { 13 | if (!isset($userInfo)) { 14 | $userInfo = new UserInfo(); 15 | } 16 | 17 | require_once(RESOURCE_DIR . "views/local_admin/usersettings.php"); 18 | 19 | } else { 20 | header('Location: /localadmin.php'); 21 | exit(); 22 | } -------------------------------------------------------------------------------- /resources/classes/Captcha/CaptchaBuilderInterface.php: -------------------------------------------------------------------------------- 1 | setWithPost(); 10 | } 11 | 12 | require_once(RESOURCE_DIR ."views/local_admin/connection_settings.php"); 13 | } 14 | // If the user is not a local admin, don't let them change the connection settings 15 | else { 16 | header("Location: /index.php"); 17 | exit(); 18 | } 19 | } 20 | 21 | else { 22 | header('Location: /index.php'); 23 | exit(); 24 | } -------------------------------------------------------------------------------- /public/settings/usersettings.php: -------------------------------------------------------------------------------- 1 | addSecretQuestionWithPost(); 8 | } 9 | elseif (isset($_POST['editSecretAnswer'])) { 10 | $userSettings->editSecretQuestionWithPost(); 11 | } 12 | elseif (isset($_POST['resetSecretQuestions'])) { 13 | $userSettings->resetSecretQuestionsForUser($_SESSION['user_name']); 14 | } 15 | 16 | require_once(RESOURCE_DIR ."views/user_settings.php"); 17 | } 18 | else { 19 | header('Location: /account.php?page=settings/usersettings.php'); 20 | exit(); 21 | } -------------------------------------------------------------------------------- /resources/functions/startPDOConnection.php: -------------------------------------------------------------------------------- 1 | setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 11 | return $db_connection; 12 | } 13 | catch (PDOException $e) { 14 | Logger::log ('error', 'Database Connection Error: ' . $e->getMessage()); 15 | return false; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /public/js/resetPrompt.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | $('#resetpw').on('click', function(e) { 3 | bootbox.dialog({ 4 | message: "By which method would you like to reset your password?", 5 | title: "Reset Password", 6 | buttons: { 7 | success: { 8 | label: "Email", 9 | className: "btn-primary", 10 | callback: function() { 11 | window.location.href = "/resetpwemail.php"; 12 | } 13 | }, 14 | main: { 15 | label: "Secret Questions", 16 | className: "btn-default", 17 | callback: function() { 18 | window.location.href = "/resetpw.php"; 19 | } 20 | } 21 | } 22 | }); 23 | 24 | return false; 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /resources/classes/Captcha/PhraseBuilder.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class PhraseBuilder implements PhraseBuilderInterface 11 | { 12 | /** 13 | * Generates random phrase of given length with given charset 14 | */ 15 | public function build($length = 5, $charset = 'abcdefghijklmnpqrstuvwxyz123456789') 16 | { 17 | $phrase = ''; 18 | $chars = str_split($charset); 19 | 20 | for ($i = 0; $i < $length; $i++) { 21 | $phrase .= $chars[array_rand($chars)]; 22 | } 23 | 24 | return $phrase; 25 | } 26 | 27 | /** 28 | * "Niceize" a code 29 | */ 30 | public function niceize($str) 31 | { 32 | return strtr(strtolower($str), '01', 'ol'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/account.php: -------------------------------------------------------------------------------- 1 | getNumOfSecretQuestions() < 3) { 11 | FlashMessage::flash('LoginError', 'The Administrator is not done configuring ADReset.
Please try again later.'); 12 | Logger::log('error', 'The user cannot login because the minimum of three secret questions are not set yet.'); 13 | require_once(RESOURCE_DIR . "views/not_logged_in.php"); 14 | } 15 | elseif (LoginCheck::isLoggedIn()) { 16 | header('Location: /settings/usersettings.php'); 17 | } 18 | else { 19 | require_once(RESOURCE_DIR . "views/not_logged_in.php"); 20 | } -------------------------------------------------------------------------------- /public/localadmin.php: -------------------------------------------------------------------------------- 1 | getAll(); 10 | // Make sure all the settings are set 11 | if (empty($ADConnectionSettings) || !$ADConnectionSettingsObject->areAllSettingsSet()) { 12 | header('Location: /settings/connectionsettings.php'); 13 | } 14 | else { 15 | header('Location: /settings/systemsettings.php'); 16 | } 17 | } 18 | elseif (LoginCheck::isLoggedIn() && LoginCheck::isDomain()) { 19 | $login->logout(); 20 | } 21 | else { 22 | require_once(RESOURCE_DIR . "/views/local_admin/not_logged_in.php"); 23 | } -------------------------------------------------------------------------------- /resources/templates/installer_navigation.php: -------------------------------------------------------------------------------- 1 | 2 | 23 | -------------------------------------------------------------------------------- /resources/classes/Config.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | <?php echo $pageTitle ?> 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /resources/core/init.php.sample: -------------------------------------------------------------------------------- 1 | array( 12 | 'type' => 'mysql', 13 | 'host' => '127.0.0.1', 14 | 'username' => 'adresetuser', 15 | 'password' => 'password', 16 | 'db_name' => 'adreset' 17 | ), 18 | 19 | 'security' => array( 20 | 'passwordLength' => 8, 21 | 'encryptionKey' => '%3Q8Eh7gFWaaT#s4F5WJQWBq8d7TFN^R' 22 | ) 23 | ); 24 | 25 | //The spl_autoload_register will automatically include the proper class file when an object is declared of that class 26 | spl_autoload_register(function($class) { 27 | require_once (RESOURCE_DIR . 'classes/' . $class . '.php'); 28 | }); 29 | 30 | //Function to sanitize user input 31 | require_once(RESOURCE_DIR . 'functions/sanitize.php'); 32 | 33 | //Function to start the database connection 34 | require_once(RESOURCE_DIR . 'functions/startPDOConnection.php'); 35 | 36 | //Function to send emails 37 | require_once(RESOURCE_DIR . 'functions/sendEmail.php'); 38 | -------------------------------------------------------------------------------- /public/ajax/testemailsettings.php: -------------------------------------------------------------------------------- 1 | 'The email was sent successfully!', 18 | 'success' => true 19 | ); 20 | } 21 | catch (Exception $e) { 22 | $returnMessage = array( 23 | 'message' => 'The email was not sent due to the following: "' . $e->getMessage() . '"', 24 | 'success' => false 25 | ); 26 | } 27 | } 28 | 29 | } 30 | else { 31 | $returnMessage = array( 32 | 'message' => 'The email was not sent due to the following: "' . 'You must be logged in as an administrator."', 33 | 'success' => false 34 | ); 35 | } 36 | 37 | header("Content-Type: application/json", true); 38 | echo json_encode($returnMessage); 39 | exit; -------------------------------------------------------------------------------- /resources/templates/navigation.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/classes/Logger.php: -------------------------------------------------------------------------------- 1 | $_SERVER['REMOTE_ADDR'], 13 | 'time' => date ("Y-m-d H:i:s"), 14 | 'user' => $_SESSION['user_name'], 15 | 'messagetype' => $messageType, 16 | 'message' => $message 17 | ); 18 | } 19 | else { 20 | $messageToLog = array( 21 | 'clientip' => $_SERVER['REMOTE_ADDR'], 22 | 'time' => date ("Y-m-d H:i:s"), 23 | 'messagetype' => $messageType, 24 | 'message' => $message 25 | ); 26 | } 27 | 28 | $messageToLog = json_encode($messageToLog) . "\n"; 29 | 30 | if ($file = fopen ($fileName, 'a')) { 31 | if (flock ($file, LOCK_EX)) { 32 | fwrite ($file, $messageToLog); 33 | flock ($file, LOCK_UN); 34 | fclose ($file); 35 | return true; 36 | } 37 | } 38 | } 39 | 40 | return false; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/templates/admin_navigation.php: -------------------------------------------------------------------------------- 1 | 33 | -------------------------------------------------------------------------------- /public/userstatus.php: -------------------------------------------------------------------------------- 1 | 'failure' 11 | ); 12 | 13 | echo json_encode($json); 14 | return false; 15 | } 16 | 17 | try { 18 | $resetPW = new ResetPW(); 19 | if ($resetPW->isUserAllowedToReset(urldecode($_GET['username']), $AD)) { 20 | $userSettings = new UserSettings(); 21 | if ($userSettings->numSecretQuestionsSetToUser(urldecode($_GET['username'])) >= 3) { 22 | $json = array ( 23 | 'status' => 'complete' 24 | ); 25 | 26 | echo json_encode($json); 27 | return true; 28 | } 29 | else { 30 | $json = array ( 31 | 'status' => 'incomplete' 32 | ); 33 | 34 | echo json_encode($json); 35 | return true; 36 | } 37 | } 38 | else { 39 | $json = array ( 40 | 'status' => 'restricted' 41 | ); 42 | 43 | echo json_encode($json); 44 | return true; 45 | } 46 | 47 | } 48 | catch (Exception $e) { 49 | // If there is an error. Continue to the default return 50 | } 51 | } 52 | 53 | $json = array ( 54 | 'status' => 'failure' 55 | ); 56 | 57 | echo json_encode($json); 58 | return false; -------------------------------------------------------------------------------- /resources/classes/PHPMailer/PHPMailerAutoload.php: -------------------------------------------------------------------------------- 1 | 8 | * @author Jim Jagielski (jimjag) 9 | * @author Andy Prevost (codeworxtech) 10 | * @author Brent R. Matzelle (original founder) 11 | * @copyright 2012 - 2014 Marcus Bointon 12 | * @copyright 2010 - 2012 Jim Jagielski 13 | * @copyright 2004 - 2009 Andy Prevost 14 | * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License 15 | * @note This program is distributed in the hope that it will be useful - WITHOUT 16 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 | * FITNESS FOR A PARTICULAR PURPOSE. 18 | */ 19 | 20 | /** 21 | * PHPMailer SPL autoloader. 22 | * @param string $classname The name of the class to load 23 | */ 24 | function PHPMailerAutoload($classname) 25 | { 26 | //Can't use __DIR__ as it's only in PHP 5.3+ 27 | $filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php'; 28 | if (is_readable($filename)) { 29 | require $filename; 30 | } 31 | } 32 | 33 | if (version_compare(PHP_VERSION, '5.1.2', '>=')) { 34 | //SPL autoloading was introduced in PHP 5.1.2 35 | if (version_compare(PHP_VERSION, '5.3.0', '>=')) { 36 | spl_autoload_register('PHPMailerAutoload', true, true); 37 | } else { 38 | spl_autoload_register('PHPMailerAutoload'); 39 | } 40 | } else { 41 | /** 42 | * Fall back to traditional autoload for old PHP versions 43 | * @param string $classname The name of the class to load 44 | */ 45 | function __autoload($classname) 46 | { 47 | PHPMailerAutoload($classname); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /resources/classes/LoginCheck.php: -------------------------------------------------------------------------------- 1 | getOtherSetting('emailresetenabled'); 5 | if (isset($isEmailResetEnabled) && $isEmailResetEnabled == 'true') { 6 | echo ''; 7 | } 8 | ?> 9 | 10 | -------------------------------------------------------------------------------- /resources/views/admin_logged_in.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 |
15 |

Logged in

16 |

Welcome . You are now logged in!

17 |

18 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum gravida sollicitudin diam ut tincidunt. Vestibulum sit amet magna auctor, suscipit est consectetur, scelerisque sapien. Pellentesque malesuada, leo in pulvinar auctor, magna justo malesuada ipsum, vel iaculis quam tortor vitae justo. Quisque consectetur gravida risus, sed efficitur turpis venenatis a. Suspendisse lobortis laoreet tristique. Aliquam sodales iaculis magna, a tristique massa pharetra ac. Cras tristique nisl aliquet, suscipit neque id, elementum risus. Nullam rutrum felis sed varius ornare. Aenean sit amet ante ultricies leo condimentum hendrerit. Donec porta ipsum ut scelerisque semper. 19 |

20 |

21 | Integer maximus quam in mi imperdiet, quis convallis lectus luctus. Sed cursus diam mauris, at hendrerit est elementum ac. Nunc luctus, massa vel consectetur tristique, risus nunc viverra enim, nec commodo sem orci nec ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse egestas velit mi, pulvinar vulputate dolor semper eu. Aliquam sollicitudin dolor et nulla aliquam, id egestas quam porta. Proin posuere sit amet metus nec tempor. Praesent nec nunc mi. Duis vestibulum maximus purus, eu venenatis metus rhoncus accumsan. Sed eget ligula et purus elementum convallis in ac erat. Mauris eget ultrices elit. Donec eu finibus ex. Sed quis mi finibus, hendrerit tellus sit amet, finibus erat. Nunc ac convallis ante, a scelerisque quam. Sed mollis interdum nibh nec lobortis. Etiam euismod sapien nec arcu maximus, non interdum nisl suscipit. 22 |

23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /resources/templates/local_navigation.php: -------------------------------------------------------------------------------- 1 | 39 | -------------------------------------------------------------------------------- /resources/functions/sendEmail.php: -------------------------------------------------------------------------------- 1 | getEmailSettings()) { 10 | if (isset($emailSettings['fromEmail']) && isset($emailSettings['fromName']) && isset($emailSettings['username']) && isset($emailSettings['password']) && isset($emailSettings['server']) && isset($emailSettings['port']) && isset($emailSettings['encryption'])) { 11 | $mail = new PHPMailer($showExceptions); 12 | $mail->isSMTP(); 13 | $mail->Host = $emailSettings['server']; 14 | $mail->SMTPAuth = true; 15 | $mail->Username = $emailSettings['username']; 16 | $mail->Password = $emailSettings['password']; 17 | 18 | if ($emailSettings['encryption'] == 'TLS') { 19 | $mail->SMTPSecure = 'tls'; 20 | } 21 | elseif ($emailSettings['encryption'] == 'SSL') { 22 | $mail->SMTPSecure = 'ssl'; 23 | } 24 | 25 | $mail->Port = $emailSettings['port']; 26 | $mail->From = $emailSettings['fromEmail']; 27 | $mail->FromName = $emailSettings['fromName']; 28 | $mail->addAddress($to); 29 | $mail->addReplyTo($emailSettings['fromEmail'], $emailSettings['fromName']); 30 | $mail->isHTML(true); 31 | $mail->Subject = $subject; 32 | $mail->Body = $body; 33 | 34 | if($mail->send()) { 35 | $systemSettings = null; 36 | return true; 37 | } 38 | } 39 | } 40 | } 41 | } 42 | 43 | $systemSettings = null; 44 | return false; 45 | } 46 | -------------------------------------------------------------------------------- /docs/Retrieving the CA Certificate used for LDAPS.md: -------------------------------------------------------------------------------- 1 | # ADReset Documentation 2 | 3 | ## Exporting the CA Certificate used for LDAPS 4 | 5 | ### Prerequisites 6 | 1. Domain Controller With: 7 | * LDAPS Enabled (Done by installing and configuring Active Directory Certificate Services on the Domain Controller and restarting) 8 | * Administrative access available 9 | 10 | ### Exporting the CA Certificate 11 |
    12 |
  1. Open the "Certificates" MMC by running:
  2. 13 | 14 | certmgr.msc 15 | 16 | 17 |
  3. Expand "Trusted Root Certificate Authorities" => click on "Certificates"

    18 | 19 |
  4. 20 | 21 |
  5. Then find the Certificate Authority that was generated during the installation of Active Directory Certificate Services. This will often be a variation of the server name and/or the domain name. The one generated for the example sky.local domain looks like the following:

    22 | 23 |
  6. 24 | 25 |
  7. Once you've found the appropriate certificate, right-click on it => hover on "All Tasks" => click on "Export"

    26 | 27 |
  8. 28 | 29 |
  9. On the "Certificate Export Wizard", click on "Next" => Select "Base-64 encoded X.509 (.CER)"

    30 | 31 |
  10. 32 | 33 |
  11. Click on "Next" => Click on "Browse" => Select a temporary location for the certificate such as your "Desktop", and name it something such as "LDAPS-CA"

    34 | 35 |
  12. 36 | 37 |
  13. Click on "Next" => Click on "Finish"
  14. 38 | 39 |
  15. Navigate to where you saved "LDAPS-CA.cer". If you are installing ADReset on Windows, just copy the certificate file over to C:\openldap\sysconf on the IIS server, otherwise, right-click on it => hover on "Open With" => click on "Notepad"

    40 | 41 |
  16. 42 | 43 |
  17. You may now copy the contents to the server you are running ADReset on

    44 | 45 |
  18. 46 |
47 | -------------------------------------------------------------------------------- /resources/classes/FlashMessage.php: -------------------------------------------------------------------------------- 1 | '; 29 | echo '
'; 30 | echo '×' . FlashMessage::flash($messageName); 31 | echo '

'; 32 | echo ''; 33 | return true; 34 | } 35 | else { 36 | echo '
'; 37 | echo '
'; 38 | echo '×' . FlashMessage::flash($messageName); 39 | echo '

'; 40 | echo '
'; 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | 47 | public static function runJsScript($messageName) { 48 | if (isset($messageName) && isset($_SESSION[$messageName])) { 49 | echo ''; 50 | unset($_SESSION[$messageName]); 51 | return true; 52 | } 53 | return false; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /resources/views/local_admin/not_logged_in.php: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 11 | 12 |
13 |
14 |
15 |
16 |

Local Administrator Login

17 |
18 | 30 |
31 |
32 | 33 |
34 | 35 |
36 |
37 |
38 | 39 |
40 | 41 |
42 |
43 |
44 |
45 |
46 | 47 | 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | -------------------------------------------------------------------------------- /resources/classes/Crypto.php: -------------------------------------------------------------------------------- 1 | 16 |
  • Ubuntu 14.04 (Apache and MySQL) Installation Guide
  • 17 |
  • Windows Server 2012 R2 (IIS and MySQL) Installation Guide
  • 18 |
  • Retrieving the CA Certificate used for LDAPS
  • 19 | 20 | 21 | ## Credits 22 | Written by Matthew Prahl except for the PHPMailer and Captcha classes 23 | 24 | ## Screenshots 25 |

    Home Screen

    26 | Home 27 | 28 |

    Home Screen - Responsive

    29 | Home Responsive 30 | 31 |

    Answering Secret Questions

    32 | Answering Secret Questions 33 | 34 |

    Selecting A New Password After Answering Questions

    35 | Selecting A New Password 36 | 37 |

    Change Password

    38 | Changing A Password 39 | 40 |

    System Settings

    41 | Home 42 | 43 | Home 44 | -------------------------------------------------------------------------------- /resources/views/reset_pw_email.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 |
    15 | 16 | 17 |
    18 |
    19 |
    20 |

    Reset Password

    21 |
    22 | 31 |
    32 |
    33 |
    34 | This form will allow you to reset your password through the email address associated with your account. Once submitted, you will receive an email with a link. Simply click on the link and set your new password. 35 |
    36 |
    37 |
    38 | 39 |
    40 | 41 |
    42 |
    43 |
    44 |
    45 |
    46 | 47 | 48 |
    49 |
    50 |
    51 |
    52 |
    53 | 54 | 55 |
    56 | 57 | 58 | -------------------------------------------------------------------------------- /resources/views/reset_pw.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 |
    15 | 16 | 17 |
    18 |
    19 |
    20 |

    Reset Password

    21 |
    22 | 31 |
    32 |
    33 |
    34 | This form will allow you to reset your password using the secret questions you defined earlier. If you have not done so, you will not be able to use this feature, therefore, contact the Help Desk for assistance with your password reset. 35 |
    36 |
    37 |
    38 | 39 |
    40 | 41 |
    42 |
    43 |
    44 |
    45 |
    46 | 47 | 48 |
    49 |
    50 |
    51 |
    52 |
    53 | 54 | 55 |
    56 | 57 | 58 | -------------------------------------------------------------------------------- /resources/functions/ADPasswordPolicyMatch.php: -------------------------------------------------------------------------------- 1 | isPWComplexityRequired(); 15 | $minPwdLength = $AD->getMinPasswordLength(); 16 | 17 | $complexityScore = 0; 18 | if ($complexityRequirement == true) { 19 | //Check if there is an uppercase 20 | if (preg_match('@[A-Z]@', $password)) { 21 | $complexityScore++; 22 | } 23 | //Check if there is a lowercase 24 | if (preg_match('@[a-z]@', $password)) { 25 | $complexityScore++; 26 | } 27 | //Check if there is a number 28 | if (preg_match('@[0-9]@', $password)) { 29 | $complexityScore++; 30 | } 31 | //Check if there is a special character 32 | if (preg_match('@[\p{P}\p{S}]@', $password)) { 33 | $complexityScore++; 34 | } 35 | 36 | //If there weren't at least three matches above, then the password is not complex enough 37 | if ($complexityScore < 3) { 38 | return false; 39 | } 40 | } 41 | 42 | if (strlen($password) >= $minPwdLength) { 43 | return true; 44 | } 45 | 46 | return false; 47 | } 48 | 49 | function ADPasswordPolicyWritten() { 50 | try { 51 | $AD = new AD(); 52 | } 53 | catch(Exception $e) { 54 | Logger::log('error', $e . ' when attempting to writeout the AD Password Policy.'); 55 | $AD = null; 56 | return 'NA'; 57 | } 58 | 59 | $complexityRequirement = $AD->isPWComplexityRequired(); 60 | $minPwdLength = $AD->getMinPasswordLength(); 61 | if ($complexityRequirement) { 62 | $AD = null; 63 | return 'The password must be ' . $minPwdLength . ' or more characters. It must also contain three of the following:
    Uppercase, Lowercase, Number, and a Special Character'; 64 | } 65 | else { 66 | $AD = null; 67 | return 'The password must be ' . $minPwdLength . ' or more characters.'; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /resources/core/structure.sql: -------------------------------------------------------------------------------- 1 | #Create localusers table 2 | DROP TABLE IF EXISTS `localusers`; 3 | CREATE TABLE IF NOT EXISTS `localusers`( 4 | id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 5 | username VARCHAR(32) NOT NULL, 6 | email VARCHAR(64) NULL, 7 | password VARCHAR(128) NOT NULL, 8 | name VARCHAR(64) NOT NULL, 9 | created DATETIME NOT NULL); 10 | 11 | #Create adconnectionsettings table 12 | DROP TABLE IF EXISTS `adconnectionsettings`; 13 | CREATE TABLE IF NOT EXISTS `adconnectionsettings`( 14 | id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 15 | setting VARCHAR(64) NOT NULL, 16 | settingvalue VARCHAR(256) NOT NULL); 17 | 18 | #Create emailreset table 19 | DROP TABLE IF EXISTS `emailreset`; 20 | CREATE TABLE IF NOT EXISTS `emailreset`( 21 | id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 22 | userguid VARCHAR(64) NOT NULL, 23 | code VARCHAR(32) NOT NULL, 24 | createtime DATETIME NOT NULL); 25 | 26 | #Create admingroups table 27 | DROP TABLE IF EXISTS `admingroups`; 28 | CREATE TABLE IF NOT EXISTS `admingroups`( 29 | id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 30 | groupguid VARCHAR(64) NOT NULL); 31 | 32 | #Create resetgroups table 33 | DROP TABLE IF EXISTS `resetgroups`; 34 | CREATE TABLE IF NOT EXISTS `resetgroups`( 35 | id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 36 | groupguid VARCHAR(64) NOT NULL); 37 | 38 | #Create emailsettings table 39 | DROP TABLE IF EXISTS `emailsettings`; 40 | CREATE TABLE IF NOT EXISTS `emailsettings`( 41 | id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 42 | setting VARCHAR(64) NOT NULL, 43 | settingvalue VARCHAR(256) NOT NULL); 44 | 45 | #Create othersettings table 46 | DROP TABLE IF EXISTS `othersettings`; 47 | CREATE TABLE IF NOT EXISTS `othersettings`( 48 | id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 49 | setting VARCHAR(64) NOT NULL, 50 | settingvalue TEXT NOT NULL); 51 | 52 | #Create secretquestions table 53 | DROP TABLE IF EXISTS `secretquestions`; 54 | CREATE TABLE IF NOT EXISTS `secretquestions`( 55 | id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 56 | secretquestion TEXT NOT NULL, 57 | enabled BIT NOT NULL); 58 | 59 | #Create usersecretquestions table 60 | DROP TABLE IF EXISTS `usersecretquestions`; 61 | CREATE TABLE IF NOT EXISTS `usersecretquestions`( 62 | id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 63 | userguid VARCHAR(64) NOT NULL, 64 | secretquestion_id INT UNSIGNED NOT NULL, 65 | secretanswer TEXT NOT NULL, 66 | FOREIGN KEY fk_question(secretquestion_id) REFERENCES secretquestions(id)); 67 | 68 | #Create sqfailedattempts table 69 | DROP TABLE IF EXISTS `sqfailedattempts`; 70 | CREATE TABLE IF NOT EXISTS `sqfailedattempts`( 71 | id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, 72 | userguid VARCHAR(64) NOT NULL, 73 | failuretime DATETIME NOT NULL); -------------------------------------------------------------------------------- /resources/views/not_logged_in.php: -------------------------------------------------------------------------------- 1 | 2 | '; 8 | } 9 | ?> 10 | 11 | 12 | 15 | 16 | 17 |
    18 | 19 | 20 |
    21 | '; 24 | } 25 | else { 26 | echo '
    '; 27 | } 28 | ?> 29 |
    30 |

    Please Login

    31 |
    32 | 41 |
    42 |
    43 | 45 |
    46 | 47 |
    48 |
    49 |
    50 | 51 |
    52 | 53 |
    54 |
    55 |
    56 |
    57 |
    58 | 59 | 60 |
    61 |
    62 |
    63 |
    64 |
    65 | 66 | 67 |
    68 | 69 | 70 | -------------------------------------------------------------------------------- /public/js/systemSettings.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | $('form.deleteAdminGroup input.btn-link').on('click', function(e){ 3 | bootbox.confirm("Are you sure you want to remove this administrative group?", function(result) { 4 | if (result) { 5 | $(e.target).closest("form").submit(); 6 | return true; 7 | } 8 | }); 9 | 10 | return false; 11 | }); 12 | 13 | $('form.deleteResetGroup input.btn-link').on('click', function(e){ 14 | bootbox.confirm("Are you sure you want to remove this reset group?", function(result) { 15 | if (result) { 16 | $(e.target).closest("form").submit(); 17 | return true; 18 | } 19 | }); 20 | 21 | return false; 22 | }); 23 | 24 | $('form.changeSecretQuestion input.btn-link').on('click', function(e){ 25 | if ($(this).val() == 'Disable') { 26 | bootbox.confirm("Are you sure you want to disable this secret question? Users using this secret question will still be able to use this question, however, the question will no longer be available for new configurations.", function(result) { 27 | if (result) { 28 | $(e.target).closest("form").submit(); 29 | return true; 30 | } 31 | }); 32 | } 33 | else { 34 | $(e.target).closest("form").submit(); 35 | return true; 36 | } 37 | 38 | return false; 39 | }); 40 | 41 | $('#testEmailSettings').on('submit', function() { 42 | $sendBtn = $(this).find('[name=sendTestEmail]'); 43 | $sendBtn.button('loading'); 44 | $.ajax({ 45 | url: $(this).attr('action'), 46 | type: 'post', 47 | cache: false, 48 | timeout: 10000, 49 | dataType: 'json', 50 | data: 'emailto=' + $(this).find('[name=email_testemailto]').val() 51 | }).done(function(response) { 52 | if (response.success) { 53 | $("#testEmailStatus").remove(); 54 | $("#testEmailSettings").append('
    ×' + response.message + '
    '); 55 | } 56 | else { 57 | $("#testEmailStatus").remove(); 58 | $("#testEmailSettings").append('
    ×' + response.message + '
    '); 59 | } 60 | }); 61 | 62 | setTimeout(function () { 63 | $sendBtn.button('reset'); 64 | $('#testEmailSettings')[0].reset(); 65 | }, 500); 66 | 67 | return false; 68 | 69 | }); 70 | }); -------------------------------------------------------------------------------- /public/resetpwemail.php: -------------------------------------------------------------------------------- 1 | getOtherSetting('emailresetenabled'); 6 | 7 | // If they are logged in then they shouldn't be resetting their password. In this case, redirect them to home. 8 | if (LoginCheck::isLoggedIn()) { 9 | header("location: /index.php"); 10 | exit(); 11 | } 12 | elseif (isset($isEmailResetEnabled) && $isEmailResetEnabled == 'true') { 13 | //If they are requesting an email password reset link, this post will exist 14 | if (isset($_POST['resetPassword'])) { 15 | $resetPW = new ResetPW(); 16 | try { 17 | $resetPW->generateAndSendCode($_POST['user_name']); 18 | } 19 | catch (Exception $e) { 20 | switch ($e->getMessage()) { 21 | case 'The user does not have permission to use ADReset': 22 | FlashMessage::flash('ResetPWError', 'You do not have permission to use ADReset. Please contact the Help Desk for assistance.'); 23 | break; 24 | case 'The Active Directory connection failed': 25 | FlashMessage::flash('ResetPWError', 'The connection to Active Directory failed. Please contact the Help Desk for assistance.'); 26 | break; 27 | case 'The email failed to send': 28 | FlashMessage::flash('ResetPWError', 'The email with your generated link failed to send. Please contact the Help Desk for assistance.'); 29 | break; 30 | case 'The database connection failed': 31 | FlashMessage::flash('ResetPWError', 'The database connection failed. Please contact the Help Desk for assistance.'); 32 | break; 33 | case 'The reset email is not properly set in Active Directory.': 34 | FlashMessage::flash('ResetPWError', 'The reset email is not properly set in Active Directory. Please contact the Help Desk for assistance.'); 35 | break; 36 | default: 37 | FlashMessage::flash('ResetPWError', 'An unexpected error occurred. Please contact the Help Desk for assistance.'); 38 | } 39 | header('Location: /resetpwemail.php'); 40 | exit(); 41 | } 42 | 43 | FlashMessage::flash('ResetPWMessage', 'The password recovery email was sent. You may now close this tab.'); 44 | header('Location: /resetpwemail.php'); 45 | exit(); 46 | } 47 | 48 | require_once(RESOURCE_DIR . "/views/reset_pw_email.php"); 49 | } 50 | else { 51 | header("location: /index.php"); 52 | exit(); 53 | } -------------------------------------------------------------------------------- /public/settings/systemsettings.php: -------------------------------------------------------------------------------- 1 | getAll(); 7 | // Make sure all the settings are set 8 | if (empty($ADConnectionSettings) || !$ADConnectionSettingsObject->areAllSettingsSet()) { 9 | echo '

    Active Directory Connection Settings Error:

    Please configure your AD Connection Settings before configuring System Settings.

    '; 10 | Logger::log ('error', 'The database could not retrieve the connection settings for Active Directory'); 11 | exit(); 12 | } 13 | 14 | $systemSettings = new SystemSettings(); 15 | 16 | if (isset($_POST['addAdminGroup'])) { 17 | $systemSettings->addAdminGroupWithPost(); 18 | header('Location: systemsettings.php'); 19 | exit(); 20 | } 21 | elseif (isset($_POST['deleteAdminGroup'])) { 22 | $systemSettings->deleteAdminGroupWithPost(); 23 | header('Location: systemsettings.php'); 24 | exit(); 25 | } 26 | elseif (isset($_POST['addResetGroup'])) { 27 | 28 | $systemSettings->addResetGroupWithPost(); 29 | header('Location: systemsettings.php'); 30 | exit(); 31 | } 32 | elseif (isset($_POST['deleteResetGroup'])) { 33 | $systemSettings->deleteResetGroupWithPost(); 34 | header('Location: systemsettings.php'); 35 | exit(); 36 | } 37 | elseif (isset($_POST['changeEmailSettings'])) { 38 | $systemSettings->setEmailSettingsWithPost(); 39 | header('Location: systemsettings.php'); 40 | exit(); 41 | } 42 | elseif (isset($_POST['updateOtherSettings'])) { 43 | $systemSettings->setOtherSettingsWithPost(); 44 | header('Location: systemsettings.php'); 45 | exit(); 46 | } 47 | elseif (isset($_POST['addSecretQuestion'])) { 48 | $systemSettings->addSecretQuestionWithPost(); 49 | header('Location: systemsettings.php'); 50 | exit(); 51 | } 52 | elseif (isset($_POST['changeSecretQuestion'])) { 53 | $systemSettings->changeSecretQuestionStatusFromPOST(); 54 | header('Location: systemsettings.php'); 55 | exit(); 56 | } 57 | 58 | $emailSettings = $systemSettings->getEmailSettings(); 59 | require_once(RESOURCE_DIR ."views/system_settings.php"); 60 | } 61 | 62 | else { 63 | header('Location: /index.php'); 64 | exit(); 65 | } -------------------------------------------------------------------------------- /resources/classes/Captcha/ImageFileHandler.php: -------------------------------------------------------------------------------- 1 | 11 | * @author Jeremy Livingston 12 | */ 13 | class ImageFileHandler 14 | { 15 | /** 16 | * Name of folder for captcha images 17 | * @var string 18 | */ 19 | protected $imageFolder; 20 | 21 | /** 22 | * Absolute path to public web folder 23 | * @var string 24 | */ 25 | protected $webPath; 26 | 27 | /** 28 | * Frequency of garbage collection in fractions of 1 29 | * @var int 30 | */ 31 | protected $gcFreq; 32 | 33 | /** 34 | * Maximum age of images in minutes 35 | * @var int 36 | */ 37 | protected $expiration; 38 | 39 | /** 40 | * @param $imageFolder 41 | * @param $webPath 42 | * @param $gcFreq 43 | * @param $expiration 44 | */ 45 | public function __construct($imageFolder, $webPath, $gcFreq, $expiration) 46 | { 47 | $this->imageFolder = $imageFolder; 48 | $this->webPath = $webPath; 49 | $this->gcFreq = $gcFreq; 50 | $this->expiration = $expiration; 51 | } 52 | 53 | /** 54 | * Saves the provided image content as a file 55 | * 56 | * @param string $contents 57 | * 58 | * @return string 59 | */ 60 | public function saveAsFile($contents) 61 | { 62 | $this->createFolderIfMissing(); 63 | 64 | $filename = md5(uniqid()) . '.jpg'; 65 | $filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename; 66 | imagejpeg($contents, $filePath, 15); 67 | 68 | return '/' . $this->imageFolder . '/' . $filename; 69 | } 70 | 71 | /** 72 | * Randomly runs garbage collection on the image directory 73 | * 74 | * @return bool 75 | */ 76 | public function collectGarbage() 77 | { 78 | if (!mt_rand(1, $this->gcFreq) == 1) { 79 | return false; 80 | } 81 | 82 | $this->createFolderIfMissing(); 83 | 84 | $finder = new Finder(); 85 | $criteria = sprintf('<= now - %s minutes', $this->expiration); 86 | $finder->in($this->webPath . '/' . $this->imageFolder) 87 | ->date($criteria); 88 | 89 | foreach($finder->files() as $file) { 90 | unlink($file->getPathname()); 91 | } 92 | 93 | return true; 94 | } 95 | 96 | /** 97 | * Creates the folder if it doesn't exist 98 | */ 99 | protected function createFolderIfMissing() 100 | { 101 | if (!file_exists($this->webPath . '/' . $this->imageFolder)) { 102 | mkdir($this->webPath . '/' . $this->imageFolder, 0755); 103 | } 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /resources/functions/installerFunctions.php: -------------------------------------------------------------------------------- 1 | The PHP version of 5.5.0 or greater is required.

    '; 6 | } 7 | } 8 | 9 | function checkModulesRequired() { 10 | // The required modules to run ADReset 11 | $modulesRequired = array( 12 | 'Core', 13 | 'PDO', 14 | 'bcmath', 15 | 'date', 16 | 'filter', 17 | 'hash', 18 | 'json', 19 | 'ldap', 20 | 'mbstring', 21 | 'mcrypt', 22 | 'openssl', 23 | 'pcre', 24 | 'session', 25 | 'SPL', 26 | 'standard', 27 | 'gd' 28 | ); 29 | 30 | // Check if the required modules are loaded 31 | foreach ($modulesRequired as $module) { 32 | if (!extension_loaded($module)) { 33 | $modulesNotInstalled[] = $module; 34 | } 35 | } 36 | 37 | if (isset($modulesNotInstalled)) { 38 | return $modulesNotInstalled; 39 | } 40 | else{ 41 | return array(); 42 | } 43 | } 44 | 45 | function generateInit($db_hostname, $db_username, $db_password, $db_dbname) { 46 | if (isset($db_hostname, $db_username, $db_password, $db_dbname)) { 47 | $initPHP = 48 | ' 49 | array( 60 | \'type\' => \'mysql\', 61 | \'host\' => \'' . $db_hostname . '\', 62 | \'username\' => \'' . $db_username . '\', 63 | \'password\' => \'' . $db_password . '\', 64 | \'db_name\' => \'' . $db_dbname . '\' 65 | ), 66 | 67 | \'security\' => array( 68 | \'passwordLength\' => 8, 69 | \'encryptionKey\' => \'' . substr(md5(rand()), 0, 32) . '\' 70 | ) 71 | ); 72 | 73 | //The spl_autoload_register will automatically include the proper class file when an object is declared of that class 74 | spl_autoload_register(function($class) { 75 | require_once (RESOURCE_DIR . \'classes/\' . $class . \'.php\'); 76 | }); 77 | 78 | //Function to sanitize user input 79 | require_once(RESOURCE_DIR . \'functions/sanitize.php\'); 80 | 81 | //Function to start the database connection 82 | require_once(RESOURCE_DIR . \'functions/startPDOConnection.php\'); 83 | 84 | //Functio to send emails 85 | require_once(RESOURCE_DIR . \'functions/sendEmail.php\'); 86 | '; 87 | return $initPHP; 88 | } 89 | 90 | else { 91 | return ''; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /resources/classes/ChangeADPassword.php: -------------------------------------------------------------------------------- 1 | AD_connection = new AD(); 11 | } 12 | catch (Exception $e) { 13 | $this->setErrorAndQuit('The Domain Controller could not be contacted.'); 14 | } 15 | } 16 | 17 | private function setErrorAndQuit($message) { 18 | if (isset($message)) { 19 | FlashMessage::flash('ChangePWError', $message); 20 | header('Location: /changepw.php'); 21 | exit(); 22 | } 23 | 24 | return false; 25 | } 26 | 27 | public function changeFromPOST() { 28 | if (isset($_POST['user_name'], $_POST['user_password'], $_POST['user_new_password'], $_POST['user_confirm_password'], $_POST['user_captcha'])) { 29 | if (trim($_POST['user_captcha']) == $_SESSION['changepw_captcha']) { 30 | if (trim($_POST['user_new_password']) == trim($_POST['user_confirm_password'])) { 31 | if (ADPasswordPolicyMatch(trim($_POST['user_new_password']))) { 32 | if ($this->AD_connection->changePassword(trim($_POST['user_name']), trim($_POST['user_password']), trim($_POST['user_new_password']))) { 33 | Logger::log('audit', 'Password Change Success: The user "' . $_POST['user_name'] . '" changed their password.'); 34 | FlashMessage::flash('ChangePWMessage', 'Your password has been changed successfully.'); 35 | header('Location: /changepw.php'); 36 | exit(); 37 | } 38 | else { 39 | Logger::log('audit', 'Password Change Failure: The user "' . $_POST['user_name'] . '" failed at changing their password.'); 40 | $this->setErrorAndQuit('Your password could not be changed due to an incorrect password. If this is an error, please contact the Help Desk.'); 41 | } 42 | } 43 | else { 44 | $this->setErrorAndQuit('Your password could not be changed because it did not meet the complexity requirements. ' . ADPasswordPolicyWritten()); 45 | } 46 | } 47 | else { 48 | $this->setErrorAndQuit('Your password could not be changed because the two entries of your new password did not match.'); 49 | } 50 | } 51 | else { 52 | $this->setErrorAndQuit('Your password could not be changed because the verification code did not match. Please try again.'); 53 | } 54 | } 55 | 56 | return false; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /resources/views/new_pw.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 10 | 11 | 12 | 15 | 16 | 17 |
    18 | 19 | 20 |
    21 |
    22 |
    23 |

    Set A New Password

    24 |
    25 | 34 |
    35 |
    36 |
    37 | To reset your password, simply type in your new password in each text box and click on the "Reset Password" button. Please remember that your new password must conform to the company's password policy. 38 |
    39 |
    40 |
    41 | 42 |
    43 | 44 |
    45 |
    46 | 47 |
    48 | 49 |
    50 | 51 |
    52 |
    53 | 54 |
    55 |
    56 |
    57 | 58 | 59 |
    60 |
    61 |
    62 |
    63 |
    64 | 65 | 66 |
    67 | 68 | 69 | -------------------------------------------------------------------------------- /public/newpw.php: -------------------------------------------------------------------------------- 1 | isCodeValidFromEmail()) { 13 | // If the code is invalid, return the user to index.php 14 | header('Location: /index.php'); 15 | exit(); 16 | } 17 | 18 | require_once(RESOURCE_DIR . '/views/new_pw.php'); 19 | } 20 | elseif (isset($_GET['idq'])) { 21 | $resetPW = new ResetPW(); 22 | if (!$resetPW->isQuestionsCodeValid($_GET['idq'])) { 23 | // If the code is invalid, return the user to index.php 24 | FlashMessage::flash('InvalidCodeError', '/js/invalidCodePrompt.js'); 25 | header('Location: /index.php'); 26 | exit(); 27 | } 28 | 29 | require_once(RESOURCE_DIR . '/views/new_pw.php'); 30 | } 31 | // If $_POST['id'] is set, that means the user submitted the new password and the hidden input with the code id was submitted with the form 32 | elseif (isset($_POST['id'])) { 33 | $resetPW = new ResetPW(); 34 | if ($resetPW->isCodeValidFromEmail()) { 35 | if (isset($_POST['setPassword'])) { 36 | if ($resetPW->setNewPassword()) { 37 | FlashMessage::flash('passwordSetMessage', '/js/passwordResetSuccess.js'); 38 | header('Location: /index.php'); 39 | exit(); 40 | } 41 | else { 42 | header('Location: /newpw.php?id=' . $_POST['id']); 43 | exit(); 44 | } 45 | } 46 | } 47 | else { 48 | // If the code is invalid, return the user to index.php 49 | header('Location: /index.php'); 50 | exit(); 51 | } 52 | } 53 | elseif (isset($_POST['idq'])) { 54 | $resetPW = new ResetPW(); 55 | if ($resetPW->isQuestionsCodeValid()) { 56 | if (isset($_POST['setPassword'])) { 57 | if ($resetPW->setNewPassword()) { 58 | FlashMessage::flash('passwordSetMessage', '/js/passwordResetSuccess.js'); 59 | header('Location: /index.php'); 60 | exit(); 61 | } 62 | else { 63 | header('Location: /newpw.php?idq=' . $_POST['id']); 64 | exit(); 65 | } 66 | } 67 | } 68 | else { 69 | // If the code is invalid, return the user to index.php 70 | header('Location: /index.php'); 71 | exit(); 72 | } 73 | } 74 | else { 75 | header("Location: /index.php"); 76 | exit(); 77 | } 78 | 79 | 80 | } 81 | 82 | ?> -------------------------------------------------------------------------------- /resources/views/verify_questions.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 |
    15 |

    Verify Your Secret Questions

    16 |
    17 |
    18 | 27 |
    28 |
    29 |
    30 |
    31 |

    32 | Secret Question Verification 33 |

    34 |
    35 |
    36 |
    37 |

    38 | Enter Your Secret Questions Below: 39 |

    40 |
    41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | getSecretQuestionsSetToUser($_GET['username']); 50 | $i = 1; 51 | foreach ($usersQuestions as $question) { 52 | ?> 53 | 54 | 55 | 56 | value=> 57 | 58 | 62 | 63 |
    Secret Questions:Secret Answers:
    >
    64 |
    65 |
    66 |
    67 | name="username"> 68 | 69 | 70 |
    71 |
    72 |
    73 | 74 |
    75 |
    76 |
    77 |
    78 |
    79 |
    80 | 81 | 82 | -------------------------------------------------------------------------------- /resources/views/change_pw.php: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 23 | 24 | 25 |
    26 | 27 | 28 |
    29 |
    30 |
    31 |

    Set Your New Password

    32 |
    33 | 42 |
    43 |
    44 |
    45 | To set your password, simply fill in the text boxes below and click on the "Change Password" button. Please remember that your new password must conform to the company's password policy. 46 |
    47 |
    48 |
    49 | 51 |
    52 | 53 |
    54 |
    55 |
    56 | 57 |
    58 | 59 |
    60 |
    61 |
    62 | 63 |
    64 | 65 |
    66 |
    67 |
    68 | 69 |
    70 | 71 |
    72 |
    73 |
    74 |
    75 |
    76 | 77 |
    78 |
    79 |
    80 | 81 |
    82 | 83 |
    84 |
    85 |
    86 |
    87 |
    88 | 89 | 90 |
    91 |
    92 |
    93 |
    94 |
    95 | 96 | 97 |
    98 | 99 | 100 | -------------------------------------------------------------------------------- /docs/Get-ADResetUserStatus.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Determines if a user's secret questions are set on ADReset. If they aren't, a browser will launch and navigate to ADReset 4 | .DESCRIPTION 5 | Determines if a user's secret questions are set on ADReset. It will query /userstatus.php with the username of the logged on user or the one specified. If they user's secret questions are not set, a browser will launch and navigate to ADReset 6 | .PARAMETER webURI 7 | This is the full link to navigate to ADReset 8 | .PARAMETER username 9 | This is the user the script will check with ADReset to see if their secret questions are configured 10 | .PARAMETER browser 11 | This is the browser that will be used to navigate to ADReset if the user's secret questions are not set 12 | 13 | .EXAMPLE 14 | .\Get-ADResetUserStatus.ps1 -webURI 'adreset.domain.local' -browser 'IE' 15 | .EXAMPLE 16 | .\Get-ADResetUserStatus.ps1 -webURI 'adreset.domain.local' -browser 'Chrome' 17 | .EXAMPLE 18 | .\Get-ADResetUserStatus.ps1 -webURI 'adreset.domain.local' -browser 'Firefox' 19 | .EXAMPLE 20 | .\Get-ADResetUserStatus.ps1 -webURI 'adreset.domain.local' -browser 'IE' -username 'john.smith' 21 | #> 22 | 23 | [CmdletBinding()] 24 | param ( 25 | [parameter(Mandatory=$true)] 26 | [string]$webURI, 27 | [parameter(Mandatory=$false)] 28 | [string]$username = $env:USERNAME, 29 | [parameter(Mandatory=$true)] 30 | [ValidateSet('IE','Chrome','Firefox')] 31 | [string]$browser 32 | ) 33 | 34 | process { 35 | #Load the proper .NET Assemblies 36 | Add-Type -Assembly System.ServiceModel.Web,System.Runtime.Serialization,System.Web 37 | 38 | # This function was written by Keith Hill and taken from https://rkeithhill.wordpress.com/2009/12/06/json-serializationdeserialization-in-powershell 39 | # This was necessary to use instead of Invoke-RestMethod because this needs to support PowerShell v2. 40 | function Convert-JsonToXml([string]$json) 41 | { 42 | $bytes = [byte[]][char[]]$json 43 | $quotas = [System.Xml.XmlDictionaryReaderQuotas]::Max 44 | $jsonReader = [System.Runtime.Serialization.Json.JsonReaderWriterFactory]::CreateJsonReader($bytes,$quotas) 45 | try 46 | { 47 | $xml = new-object System.Xml.XmlDocument 48 | 49 | $xml.Load($jsonReader) 50 | return $xml 51 | } 52 | finally 53 | { 54 | $jsonReader.Close() 55 | } 56 | } 57 | 58 | function StartBrowser() { 59 | switch ($browser) { 60 | 'IE' { 61 | $browserPaths = @( 62 | 'C:\Program Files\Internet Explorer\iexplore.exe', 63 | 'C:\Program Files (x86)\Internet Explorer\iexplore.exe' 64 | ) 65 | } 66 | 67 | 'Chrome' { 68 | $browserPaths = @( 69 | 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe', 70 | 'C:\Program Files\Google\Chrome\Application\chrome.exe' 71 | ) 72 | $browserParameters = '--new-window' 73 | } 74 | 75 | 'Firefox' { 76 | $browserPaths = @( 77 | 'C:\Program Files (x86)\Mozilla Firefox\firefox.exe', 78 | 'C:\Program Files\Mozilla Firefox\firefox.exe' 79 | ) 80 | } 81 | } 82 | 83 | if ($browserPaths -ne $null) { 84 | foreach ($browserPath in $browserPaths) { 85 | if (Test-Path $browserPath) { 86 | if ($browserParameters -ne $null) { 87 | Invoke-Expression ("& '" + $browserPath + "' '" + $browserParameters + " " + $webURI + "/account.php?notify=yes'") 88 | } 89 | else { 90 | Invoke-Expression ("& '" + $browserPath + "' '" + $webURI + "/account.php?notify=yes'") 91 | } 92 | 93 | return $true 94 | } 95 | } 96 | } 97 | 98 | return $false 99 | } 100 | 101 | try { 102 | $uri = $webURI + '/userstatus.php?username=' + [System.Web.HttpUtility]::UrlEncode($username) 103 | $resultInXML = (Convert-JsonToXml (New-Object Net.WebClient).DownloadString($uri)) 104 | if ($resultInXML.root.status.'#text' -ne $null) { 105 | if ($resultInXML.root.status.'#text' -ne $null) { 106 | if ($resultInXML.root.status.'#text' -eq 'incomplete') { 107 | if (StartBrowser) { 108 | return $true 109 | } 110 | } 111 | elseif (($resultInXML.root.status.'#text' -eq 'complete') -or ($resultInXML.root.status.'#text' -eq 'restricted')) { 112 | return $true 113 | } 114 | } 115 | } 116 | } 117 | catch { 118 | return $false 119 | } 120 | 121 | return $false 122 | } -------------------------------------------------------------------------------- /public/css/styles.css: -------------------------------------------------------------------------------- 1 | /* If screen size is less than 768 px */ 2 | 3 | @media only screen and (max-width : 768px) { 4 | p.indexOptions { 5 | margin:auto; 6 | } 7 | 8 | p.indexHeader { 9 | font-weight:normal; 10 | text-align:center; 11 | } 12 | 13 | .navbar-brand img { 14 | height: 40px; 15 | margin-top: -10px; 16 | } 17 | } 18 | 19 | /* If screen size is more than 768 px */ 20 | @media only screen and (min-width : 768px) { 21 | .navbar-brand, 22 | .navbar-nav li a { 23 | height: 80px; 24 | padding-top: 30px !important; 25 | } 26 | 27 | .navbar-brand img { 28 | height: 55px; 29 | margin-top: -18px; 30 | } 31 | 32 | .dropdown-menu li a { 33 | height: 50px; 34 | padding-top: 14px !important; 35 | text-align:left; 36 | } 37 | 38 | .divider { 39 | display:block !important; 40 | } 41 | 42 | .infoBlurb { 43 | width:69%; 44 | margin:auto; 45 | margin-bottom:3% !important; 46 | } 47 | 48 | div.resetPwWell, div.indexWell { 49 | width:50%; 50 | } 51 | 52 | .flash-alert { 53 | width: 50% !important; 54 | } 55 | 56 | .infoBlurb { 57 | width:80%; 58 | } 59 | 60 | input.addGroupInput, 61 | input.addSecretQuestion { 62 | width: 50% !important; 63 | } 64 | 65 | .width-fifty { 66 | width:50%; 67 | } 68 | 69 | .width-forty { 70 | width:40%; 71 | } 72 | 73 | } 74 | 75 | /* If screen size is more than 1200 px */ 76 | @media only screen and (min-width : 1200px) { 77 | .panel-body table { 78 | margin-left:1.75em; 79 | max-width: 90%; 80 | } 81 | 82 | .systemSettingsSubheader, .emailtest-alert, .verifyQuestionsSubheader { 83 | margin-left:1.75em; 84 | } 85 | } 86 | 87 | .bold { 88 | font-weight:bold; 89 | } 90 | 91 | .block { 92 | display:block; 93 | } 94 | 95 | p.indexOptions { 96 | text-align:center; 97 | width:200px; 98 | } 99 | 100 | p.indexOptions a.btn-primary { 101 | width:172px; 102 | margin-bottom:10px; 103 | } 104 | 105 | p.indexOptions a.disabled { 106 | pointer-events: auto; 107 | } 108 | 109 | .dropdown-menu li:hover a { 110 | color:#FFF !important; 111 | background-color: #3A536B !important; 112 | } 113 | 114 | /* Hide the divider in the mobile menu */ 115 | .divider { 116 | display:none; 117 | } 118 | 119 | a:focus, button:focus { 120 | outline:0 !important; 121 | } 122 | 123 | ul.nav.navbar-nav > li > a { 124 | transition: background-color .25s ease; 125 | -webkit-transition: background-color .25s ease; 126 | -moz-transition: background-color .25s ease; 127 | -o-transition: background-color .25s ease; 128 | } 129 | 130 | ul.nav.navbar-nav li ul { 131 | transition: all .25s ease; 132 | } 133 | 134 | ul.nav.navbar-nav li a:hover { 135 | background-color: #3A536B; 136 | } 137 | 138 | ul.navbar-nav li.dropdown.open a.dropdown-toggle { 139 | background-color: #3A536B !important; 140 | } 141 | 142 | .topHeader { 143 | text-align:center; 144 | padding-bottom:1em; 145 | } 146 | 147 | .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus, .navbar-default .navbar-nav>li>a:hover, .navbar-default .navbar-nav>li>a:focus { 148 | color:#ffffff; 149 | } 150 | 151 | .navbar-nav .dropdown-menu>li>a { 152 | padding-right:25px; 153 | } 154 | 155 | .form-control { 156 | max-width:850px; 157 | } 158 | 159 | .flash-alert { 160 | width: 90%; 161 | text-align: center; 162 | margin: auto; 163 | } 164 | 165 | .emailtest-alert { 166 | max-width: 300px; 167 | margin-top: 2em; 168 | margin-right: 2em; 169 | text-align: center; 170 | } 171 | 172 | .tool-tip, .tool-tip:hover, .tool-tip:visited { 173 | color:#2c3e50; 174 | text-decoration: none !important; 175 | font-weight:bold; 176 | } 177 | 178 | .tool-tip:hover { 179 | text-decoration: underline; 180 | } 181 | 182 | .settings-tooltip, .settings-tooltip:hover, .settings-tooltip:visited { 183 | color:#2c3e50; 184 | text-decoration: none; 185 | } 186 | 187 | .settings-tooltip:hover { 188 | text-decoration: underline; 189 | } 190 | 191 | .infoBlurb { 192 | margin:auto; 193 | margin-bottom:5%; 194 | } 195 | 196 | div.resetPwWell, div.indexWell { 197 | margin:auto; 198 | margin-bottom:3em; 199 | } 200 | 201 | input.btn-link, input.btn-link:focus { 202 | outline:0 !important; 203 | color: #2c3e50; 204 | font-weight:bold; 205 | padding: 0; 206 | } 207 | 208 | input.btn-link:hover { 209 | color: #2c3e50; 210 | } 211 | 212 | form.btn-link-form { 213 | margin-bottom: 0; 214 | } 215 | 216 | input.addGroupInput, 217 | input.addSecretQuestion { 218 | height: 35px; 219 | width: 80%; 220 | } 221 | 222 | input.addGroupBtn, 223 | input.addSecretQuestionBtn { 224 | padding-top: 5px; 225 | } 226 | 227 | .systemSettingsSubheader, 228 | .verifyQuestionsSubheader { 229 | font-weight:bold; 230 | font-size:110%; 231 | margin-bottom:1em; 232 | } 233 | 234 | .secretQuestionSelect { 235 | margin:auto; 236 | text-align:center; 237 | max-width:300px; 238 | } 239 | 240 | .center { 241 | vertical-align:middle !important; 242 | text-align:center; 243 | } 244 | 245 | .resetQuestionsBtn { 246 | margin-left: 3em; 247 | margin-bottom: 2em; 248 | } -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 23 | 24 | 32 | 33 |
    34 |
    35 |
    36 |
    37 |

    Password Reset Portal

    38 |
    39 |
    40 |
    41 |
    42 |
    43 |

    44 | What would you like to do? 45 |

    46 |
    47 |
    48 |
    49 |
    50 |

    51 | ADReset allows you to reset your Windows (Active Directory) password via secret questions or a secondary email. 52 | To set your secret questions, click on the "Set Questions" button and then login. Your password cannot be reset via this method until your secret questions are set. 53 | You may also simply change your password without resetting it by simply entering your current password and your new password. To do so, simply click on "Change Password". 54 |


    55 | 56 |

    57 | Please select an option below: 58 |

    59 |

    60 | Set Questions
    '; 63 | } 64 | else { 65 | echo 'Set Questions
    '; 66 | } 67 | ?> 68 | Change Password
    69 | Reset with Email
    '; 72 | echo 'Reset with Questions
    '; 73 | } 74 | else { 75 | echo 'Reset with Questions
    '; 76 | 77 | $systemSettings = new SystemSettings; 78 | $isEmailResetEnabled = $systemSettings->getOtherSetting('emailresetenabled'); 79 | if (isset($isEmailResetEnabled) && $isEmailResetEnabled == 'true') { 80 | echo 'Reset with Email
    '; 81 | } 82 | else { 83 | echo 'Reset with Email
    '; 84 | } 85 | } 86 | ?> 87 |

    88 |
    89 |
    90 |
    91 |
    92 |
    93 |
    94 |
    95 |
    96 |
    97 |
    98 | 99 | 100 | -------------------------------------------------------------------------------- /resources/views/local_admin/connection_settings.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 |
    15 |

    Connection Settings

    16 |

    Welcome ,

    17 |
    18 |
    19 | 28 |
    29 |

    What would you like to change?

    30 |
    31 | 32 |
    33 |
    34 |

    35 | Domain Connection Settings 36 |

    37 |
    38 |
    39 |
    40 |

    41 | Enter the connection information below: 42 |

    43 |
    44 |
    45 |
    46 | 49 |
    50 | 51 |
    52 |
    53 |
    54 | 57 |
    58 | 59 |
    60 |
    61 |
    62 | 65 |
    66 | 67 |
    68 |
    69 |
    70 | 71 |
    72 | 73 |
    74 |
    75 |
    76 | 79 |
    80 | 81 |
    82 |
    83 |
    84 |
    85 |
    86 | 87 | 88 |
    89 |
    90 |
    91 |
    92 |
    93 |
    94 |
    95 |
    96 |
    97 | 98 | 99 | -------------------------------------------------------------------------------- /resources/classes/Login.php: -------------------------------------------------------------------------------- 1 | logout(); 15 | } 16 | } 17 | 18 | // Check the to see if the administrator is trying to log in or off 19 | if (isset($_GET["logout"])) { 20 | $this->logout(); 21 | } 22 | // If the login form was submitted, then call the doLoginWithPostData function 23 | elseif (isset($_POST["login"])) { 24 | $this->loginWithPOST(); 25 | } 26 | } 27 | 28 | public function __destruct() { 29 | $this->db_connection = null; 30 | } 31 | 32 | protected function setLoginErrorAndQuit($message) { 33 | if (isset($message)) { 34 | FlashMessage::flash('LoginError', $message); 35 | header('Location: /localadmin.php'); 36 | exit(); 37 | } 38 | } 39 | 40 | private function loginWithPOST() { 41 | // Verfiy the contents that were submitted by the form 42 | if (empty($_POST['user_name'])) { 43 | $this->setLoginErrorAndQuit('The Username field was empty.'); 44 | } 45 | elseif (empty($_POST['user_password'])) { 46 | $this->setLoginErrorAndQuit('The Password field was empty.'); 47 | } 48 | elseif (!empty($_POST['user_name']) && !empty($_POST['user_password'])) { 49 | // Start the database connection 50 | if ($this->db_connection = startPDOConnection()) { 51 | // Trimming the whitespace. The input is not sanitized because prepared statements are being used 52 | $user_name = trim($_POST['user_name']); 53 | 54 | // The database query which allows the administrator to login via email address or by username. 55 | $stmt = $this->db_connection->prepare('SELECT username, email, password FROM localusers WHERE username = ? OR email = ?'); 56 | $stmt->execute(array($user_name, $user_name)); 57 | 58 | // If the user exists, then verfiy the password 59 | if ($stmt->rowCount() == 1) { 60 | 61 | // Get the user row as an array 62 | $user = $stmt->fetch(PDO::FETCH_ASSOC); 63 | $stmt = null; 64 | 65 | // Using PHP 5.5's password_verify() function to check if the provided password matches the hash of the password entered 66 | if (password_verify($_POST['user_password'], $user['password'])) { 67 | 68 | // Write the administrator's data into a PHP SESSION 69 | $_SESSION['user_name'] = $user['username']; 70 | $_SESSION['user_email'] = $user['email']; 71 | //The user's privilege is always admin from this console 72 | $_SESSION['privilege'] = 'admin'; 73 | $_SESSION['auth_source'] = 'local'; 74 | $_SESSION['user_login_status'] = 1; 75 | 76 | Logger::log('audit', 'Local Admin Login Success: The local administrator "' . $user_name . '" successfully logged in'); 77 | //The login is complete, redirect them 78 | header('Location: /localadmin.php'); 79 | exit(); 80 | 81 | } 82 | // If the username or password is incorrect, notify the administrator trying to log in 83 | else { 84 | Logger::log('audit', 'Local Admin Login Failure: The local administrator "' . $user_name . '" failed to login due to an incorrect password'); 85 | $this->setLoginErrorAndQuit('The Username or Password is incorrect.
    Please try again.'); 86 | } 87 | } 88 | // If the username or password is incorrect, notify the administrator trying to log in 89 | else { 90 | Logger::log('audit', 'Local Admin Login Failure: The local administrator "' . $user_name . '" failed to login due to an incorrect username'); 91 | $this->setLoginErrorAndQuit('The Username or Password is incorrect.
    Please try again.'); 92 | } 93 | } 94 | // If the database connection fails, notify the administrator trying to log in 95 | else { 96 | Logger::log('error', 'The local administrator "' . $user_name . '" failed to login due to a database connection issue'); 97 | $this->setLoginErrorAndQuit('There was a problem connecting to the database.
    Please try again.'); 98 | } 99 | } 100 | } 101 | 102 | public function logout() { 103 | if (isset($_SESSION['user_name'])) { 104 | Logger::log ('audit', 'Logout Success: The user "' . $_SESSION['user_name'] . '"" logged out'); 105 | } 106 | 107 | // Delete the administrator's session 108 | $_SESSION = array(); 109 | session_destroy(); 110 | // Redirect them to the login page. 111 | header('Location: /localadmin.php'); 112 | exit(); 113 | } 114 | 115 | public function isUserLoggedIn() { 116 | if (isset($_SESSION['user_login_status']) && $_SESSION['user_login_status'] == 1) { 117 | if ($_SESSION['privilege'] == 'admin') { 118 | return true; 119 | } 120 | else { 121 | $_SESSION = array(); 122 | session_destroy(); 123 | return false; 124 | } 125 | } 126 | // default return 127 | return false; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /public/verifyquestions.php: -------------------------------------------------------------------------------- 1 | getMessage())); 16 | header("Location: /resetpw.php"); 17 | exit(); 18 | } 19 | 20 | //Check to make sure there haven't been more than 5 failed attempts 21 | $systemSettings = new SystemSettings(); 22 | $resetPW = new ResetPW(); 23 | if ($failedAttemptsAllowed = $systemSettings->getOtherSetting('failedattemptsallowed')) { 24 | if ($resetPW->getNumberOfFailedAttempts($_GET['username']) >= intval($failedAttemptsAllowed)) { 25 | FlashMessage::flash('ResetPWError', 'You have failed to verify your secret questions too many times and your account is locked. Please contact the Help Desk for assistance.'); 26 | header("Location: /resetpw.php"); 27 | exit(); 28 | } 29 | } 30 | else { 31 | FlashMessage::flash('ResetPWError', 'There was a database error. Please try again.'); 32 | header("Location: /resetpw.php"); 33 | exit(); 34 | } 35 | 36 | // Make sure the user has three questions set 37 | $userSettings = new UserSettings(); 38 | try { 39 | if ($userSettings->numSecretQuestionsSetToUser(urldecode($_GET['username'])) < 3) { 40 | FlashMessage::flash('ResetPWError', 'You cannot use this feature because you do not have your secret questions set.'); 41 | header("Location: /resetpw.php"); 42 | exit(); 43 | } 44 | } 45 | catch (Exception $e) { 46 | FlashMessage::flash('ResetPWError', 'There was a database error. Please try again.'); 47 | header("Location: /resetpw.php"); 48 | exit(); 49 | } 50 | 51 | // Make sure the user is allowed to reset their password 52 | if ($resetPW->isUserAllowedToReset(urldecode($_GET['username']), $AD)) { 53 | require_once(RESOURCE_DIR . '/views/verify_questions.php'); 54 | } 55 | else { 56 | FlashMessage::flash('ResetPWError', 'You are not permitted to use this feature. Please contact the Help Desk for assistance.'); 57 | header("Location: /resetpw.php"); 58 | exit(); 59 | } 60 | 61 | } 62 | elseif (isset($_POST['verifySecretQuestions'])) { 63 | if (isset($_POST['secretQuestion1'], $_POST['secretQuestion2'], $_POST['secretQuestion3'], $_POST['secretAnswer1'], $_POST['secretAnswer2'], $_POST['secretAnswer3'], $_POST['username'])) { 64 | $userSettings = new UserSettings(); 65 | 66 | // Make sure ADReset can connect to Active Directory 67 | try { 68 | $AD = new AD(); 69 | } 70 | catch (Exception $e) { 71 | FlashMessage::flash('ResetPWError', sanitize($e->getMessage())); 72 | header("Location: /resetpw.php"); 73 | exit(); 74 | } 75 | 76 | $resetPW = new ResetPW(); 77 | // Make sure the user is allowed to reset their password 78 | if (!$resetPW->isUserAllowedToReset($_POST['username'], $AD)) { 79 | FlashMessage::flash('ResetPWError', 'You are not permitted to use this feature. Please contact the Help Desk for assistance.'); 80 | header("Location: /resetpw.php"); 81 | exit(); 82 | } 83 | 84 | //Check to make sure there haven't been more than 5 failed attempts 85 | $systemSettings = new systemSettings(); 86 | if ($failedAttemptsAllowed = $systemSettings->getOtherSetting('failedattemptsallowed')) { 87 | if ($resetPW->getNumberOfFailedAttempts($_GET['username']) >= intval($failedAttemptsAllowed)) { 88 | FlashMessage::flash('ResetPWError', 'You have failed to verify your secret questions too many times and your account is locked. Please contact the Help Desk for assistance.'); 89 | header("Location: /resetpw.php"); 90 | exit(); 91 | } 92 | } 93 | else { 94 | FlashMessage::flash('ResetPWError', 'There was a database error. Please try again.'); 95 | header("Location: /resetpw.php"); 96 | exit(); 97 | } 98 | 99 | if ($resetPW->getNumberOfFailedAttempts($_POST['username']) >= 5) { 100 | FlashMessage::flash('ResetPWError', 'You have failed to verify your secret questions too many times and your account is locked. Please contact the Help Desk for assistance.'); 101 | header("Location: /resetpw.php"); 102 | exit(); 103 | } 104 | 105 | // Verify the questions and set a temporary code if successful 106 | if (!empty($_POST['secretQuestion1']) && !empty($_POST['secretQuestion2']) && !empty($_POST['secretQuestion3']) && !empty($_POST['secretAnswer1']) && !empty($_POST['secretAnswer2']) && !empty($_POST['secretAnswer3']) && !empty($_POST['username'])) { 107 | $userSettings = new UserSettings(); 108 | if ($resetPW->verifySecretQuestionSetToUser($_POST['username'], $_POST['secretQuestion1'], $_POST['secretAnswer1']) && $resetPW->verifySecretQuestionSetToUser($_POST['username'], $_POST['secretQuestion2'], $_POST['secretAnswer2']) && $resetPW->verifySecretQuestionSetToUser($_POST['username'], $_POST['secretQuestion3'], $_POST['secretAnswer3'])) { 109 | $resetPW = new ResetPW(); 110 | if ($generatedcode = $resetPW->generateQuestionsCode($_POST['username'])) { 111 | header("Location: /newpw.php?idq=" . $generatedcode); 112 | exit(); 113 | } 114 | } 115 | 116 | // Record the failed login in the database 117 | $resetPW->setFailedAttempt($_POST['username']); 118 | FlashMessage::flash('ResetPWError', 'The secret questions provided were incorrect. Please try again.'); 119 | header("Location: /resetpw.php"); 120 | exit(); 121 | } 122 | } 123 | 124 | } 125 | else { 126 | header("Location: /resetpw.php"); 127 | exit(); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /resources/classes/UserInfo.php: -------------------------------------------------------------------------------- 1 | db_connection = startPDOConnection()) { 11 | echo '

    Database Connection Error:

    Please contact the Help Desk with this error.

    '; 12 | die(); 13 | } 14 | } 15 | 16 | public function __destruct() { 17 | $this->db_connection = null; 18 | } 19 | 20 | protected function setErrorAndQuit($message) { 21 | if (isset($message)) { 22 | FlashMessage::flash('ChangeProfileError', $message); 23 | header('Location: /settings/localusersettings.php'); 24 | exit(); 25 | } 26 | } 27 | 28 | public function get($user_username = ''){ 29 | if (empty($user_username)) { 30 | if (isset($_SESSION['user_name'])) { 31 | $user_username = isset($_SESSION['user_name']); 32 | } 33 | else { 34 | return array(); 35 | } 36 | } 37 | 38 | if (isset($_SESSION['user_name']) && $this->db_connection) { 39 | $user_username = $_SESSION['user_name']; 40 | $stmt = $this->db_connection->prepare('SELECT username, email, name, created FROM localusers WHERE username = ?'); 41 | 42 | if ($stmt->execute(array($user_username))) { 43 | // If this user exists return the results 44 | if ($stmt->rowCount() == 1) { 45 | $userInfo = $stmt->fetch(PDO::FETCH_ASSOC); 46 | //Close the connection 47 | $stmt = null; 48 | return $userInfo; 49 | } 50 | else { 51 | return array(); 52 | } 53 | } 54 | } 55 | else { 56 | return array(); 57 | } 58 | } 59 | 60 | public function setProfile($user_username = '') { 61 | if (empty($user_username)) { 62 | if (isset($_SESSION['user_name'])) { 63 | $user_username = isset($_SESSION['user_name']); 64 | } 65 | else { 66 | return false; 67 | } 68 | } 69 | 70 | if ($this->db_connection) { 71 | $user_newusername = trim($_POST['user_newusername']); 72 | $user_name = trim($_POST['user_newname']); 73 | $user_email = trim($_POST['user_newemail']); 74 | 75 | if ($this->get($user_username)['username'] != $user_newusername){ 76 | $stmt = $this->db_connection->prepare('SELECT username FROM localusers WHERE username = ?'); 77 | 78 | if($stmt->execute(array($user_newusername))) { 79 | // if this username is already taken 80 | if ($stmt->rowCount() != 0) { 81 | //Close the connections 82 | $stmt = null; 83 | FlashMessage::flash('ChangeProfileError', 'This username is already taken.'); 84 | header('Location: /settings/localusersettings.php'); 85 | exit(); 86 | } 87 | } 88 | $stmt = null; 89 | } 90 | 91 | if ($this->get($user_username)['email'] != $user_email){ 92 | $stmt = $this->db_connection->prepare('SELECT email FROM localusers WHERE email = ?'); 93 | 94 | if ($stmt->execute(array($user_email))) { 95 | // if this username is already taken 96 | if ($stmt->rowCount() != 0) { 97 | //Close the connections 98 | $stmt = null; 99 | $this->setErrorAndQuit('This email address is already taken.'); 100 | } 101 | } 102 | $stmt = null; 103 | } 104 | 105 | if (strlen($user_newusername) > 64 || strlen($user_newusername) < 2) { 106 | $this->setErrorAndQuit('Password does not conform to the password policy.
    '. passwordPolicyWritten()); 107 | } 108 | elseif (!preg_match('/^[a-zA-Z0-9]*[_.-]?[a-zA-Z0-9]*$/', $user_newusername)) { 109 | $this->setErrorAndQuit('Username does not match the naming scheme. Only letters, numbers, underscores, and periods are allowed'); 110 | } 111 | elseif (empty($user_email)) { 112 | $this->setErrorAndQuit('Email cannot be empty.'); 113 | } 114 | elseif (strlen($user_email) > 64) { 115 | $this->setErrorAndQuit('Email cannot be longer than 64 characters.'); 116 | } 117 | elseif (!filter_var($user_email, FILTER_VALIDATE_EMAIL)) { 118 | $this->setErrorAndQuit('Your email address is not in a valid email format.'); 119 | } 120 | elseif (!empty($user_newusername) 121 | && strlen($user_newusername) <= 64 122 | && strlen($user_newusername) >= 2 123 | && preg_match('/^[a-zA-Z0-9]*[_.-]?[a-zA-Z0-9]*$/', $user_newusername) 124 | && !empty($user_email) 125 | && strlen($user_email) <= 64 126 | && filter_var($user_email, FILTER_VALIDATE_EMAIL) 127 | ) { 128 | $user_name = $_POST['user_newname']; 129 | $user_email = $_POST['user_newemail']; 130 | $stmt = $this->db_connection->prepare('UPDATE localusers SET username = ?, name = ?, email = ? WHERE username = ?'); 131 | 132 | if ($stmt->execute(array($user_newusername, $user_name, $user_email, $user_username))) { 133 | $_SESSION['user_name'] = $user_newusername; 134 | Logger::log('audit', 'Local Admin Profile Change Success: Profile of User "' . $user_username . '" was set to User "' . $user_newusername . '", Name "' . $user_name . '", Email "' . $user_email . '"'); 135 | FlashMessage::flash('ChangeProfileMessage', 'Profile was successfully modified.'); 136 | header('Location: /settings/localusersettings.php'); 137 | exit(); 138 | } 139 | else { 140 | $this->setErrorAndQuit('Profile could not be modified.'); 141 | } 142 | } 143 | } 144 | else { 145 | $this->setErrorAndQuit('There was a problem connecting to the database. Please try again.'); 146 | } 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /resources/views/local_admin/usersettings.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 |
    15 |

    Settings

    16 |

    Welcome ,

    17 |
    18 |
    19 | 34 |
    35 |

    What would you like to change?

    36 |
    37 | 38 |
    39 |
    40 |

    41 | Change Password 42 |

    43 |
    44 |
    45 |
    46 |
    47 |
    48 |
    49 | 50 |
    51 | 52 |
    53 |
    54 |
    55 | 56 |
    57 | value="" autocomplete="off"> 58 |
    59 |
    60 |
    61 | 62 |
    63 | value="" autocomplete="off"> 64 |
    65 |
    66 |
    67 |
    68 |
    69 | 70 | 71 |
    72 |
    73 |
    74 |
    75 |
    76 |
    77 |
    78 | 79 | 80 |
    81 |
    82 |

    83 | Change Profile 84 |

    85 |
    86 |
    87 |
    88 |
    89 |
    90 |
    91 | 92 |
    93 | autocomplete="off"> 94 |
    95 |
    96 |
    97 | 98 |
    99 | get()['name']) . '"';?> autocomplete="off"> 100 |
    101 |
    102 |
    103 | 104 |
    105 | get()['email']) . '"';?> autocomplete="off"> 106 |
    107 |
    108 |
    109 |
    110 |
    111 | 112 | 113 |
    114 |
    115 |
    116 |
    117 |
    118 |
    119 |
    120 | 121 | 122 |
    123 |
    124 |

    125 | Security Settings 126 |

    127 |
    128 |
    129 |
    130 | No security settings are configurable yet. 131 |
    132 |
    133 |
    134 | 135 |
    136 | 137 |
    138 | 139 | 140 | -------------------------------------------------------------------------------- /resources/views/user_settings.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 12 | 13 | 14 | 15 |
    16 |

    User Settings

    17 |

    Welcome ,

    18 |
    19 |
    20 | numSecretQuestionsSetToUser($_SESSION['user_name'])) < 3) { 29 | ?> 30 |
    31 | 36 |
    37 | 41 |
    42 |

    What would you like to change?

    43 |
    44 |
    45 |
    46 |

    47 | User Settings 48 |

    49 |
    50 |
    51 |
    52 |

    53 | Manage Your Secret Questions Below: 54 |

    55 |
    56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | getSecretQuestionsSetToUser($_SESSION['user_name']); 65 | foreach ($usersQuestions as $question) { 66 | echo ' 67 | 68 | 69 | 70 | 71 | 72 | 73 | '; 74 | } 75 | 76 | $numSecretQuestionsSet = $userSettings->numSecretQuestionsSetToUser($_SESSION['user_name']); 77 | if ($numSecretQuestionsSet < 3) { 78 | for ($i = $numSecretQuestionsSet; $i < 3; $i++) { 79 | echo ' 80 | 81 | 95 | 96 | 97 | 98 | '; 99 | } 100 | // Disable the input for subsequent questions 101 | else { 102 | echo ' 103 | 104 | 105 | 106 | '; 107 | } 108 | 109 | } 110 | } 111 | ?> 112 | 113 |
    Secret Questions:Secret Answers:Actions:
    ', $question, '
    '; 82 | 83 | $secretQuestions = $userSettings->getUniqueSecretQuestionsForUser($_SESSION['user_name']); 84 | 85 | echo ''; 91 | 92 | // Allow input on the next quesiton needed to be filled 93 | if ($i == $numSecretQuestionsSet) { 94 | echo '
    114 |
    115 |
    116 | 117 |
    118 | 119 | 120 |
    121 |
    122 |
    123 |
    124 |
    125 | 126 | 127 | -------------------------------------------------------------------------------- /resources/classes/ChangePassword.php: -------------------------------------------------------------------------------- 1 | changeThePassword(); 15 | } 16 | 17 | public function __destruct() { 18 | $this->db_connection = null; 19 | } 20 | 21 | protected function setErrorAndQuit($message) { 22 | if (isset($message)) { 23 | FlashMessage::flash('ChangePWError', $message); 24 | header('Location: /settings/localusersettings.php'); 25 | exit(); 26 | } 27 | else { 28 | header('Location: /settings/localusersettings.php'); 29 | exit(); 30 | } 31 | } 32 | 33 | private function changeThePassword() { 34 | // If the POST data of user_oldpassword doesn't exist, store a flash message in the user's session and redirect them to the usersettingspage 35 | if (!isset($_POST['user_oldpassword'])) { 36 | $this->setErrorAndQuit('Old Password field was empty.'); 37 | } 38 | // If the POST data of user_newpassword doesn't exist, store a flash message in the user's session and redirect them to the usersettingspage 39 | elseif (!isset($_POST['user_newpassword'])) { 40 | $this->setErrorAndQuit('New Password field was empty.'); 41 | } 42 | // If the POST data of user_confirmnewpassword doesn't exist, store a flash message in the user's session and redirect them to the usersettingspage 43 | elseif (!isset($_POST['user_confirmnewpassword'])) { 44 | $this->setErrorAndQuit('Confirm New Password field was empty.'); 45 | } 46 | // If the POST data of user_oldpassword is not equal to user_newpassword, store a flash message in the user's session and redirect them to the usersettingspage 47 | elseif ($_POST['user_oldpassword'] == $_POST['user_newpassword']) { 48 | $this->setErrorAndQuit('Old Password and New Password are the same.'); 49 | } 50 | // If the POST data of user_newpassword is not equal to user_confirmnewpassword, store a flash message in the user's session and redirect them to the usersettingspage 51 | elseif ($_POST['user_newpassword'] != $_POST['user_confirmnewpassword']) { 52 | $this->setErrorAndQuit('Passwords do not match.'); 53 | } 54 | // If the POST data of user_newpassword doesn't pass the passwordPolicyMatch function, store a flash message in the user's session and redirect them to the usersettingspage 55 | elseif (!passwordPolicyMatch($_POST['user_newpassword'])) { 56 | $this->setErrorAndQuit('Password does not conform to the password policy.
    '. passwordPolicyWritten()); 57 | } 58 | // If all the required POST values that are required exist, then proceed with the password change 59 | elseif (isset($_POST['user_oldpassword']) && isset($_POST['user_newpassword']) && !empty($_POST['user_confirmnewpassword'])) { 60 | // If the database connection was successful, then continue on 61 | if ($this->db_connection = startPDOConnection()) { 62 | // Trim any whitespace, saniziting the data is not required because prepared statements are used 63 | $user_oldpassword = trim($_POST['user_oldpassword']); 64 | 65 | // A database query to get all user info of the logged in administrator 66 | $stmt = $this->db_connection->prepare('SELECT username, email, password FROM localusers WHERE username = ?'); 67 | $stmt->execute(array($_SESSION['user_name'])); 68 | 69 | // If the administrator exists then continue on with the password change 70 | if ($stmt->rowCount()== 1) { 71 | // Get the results as an array so the password can be queried from the user 72 | $user = $stmt->fetch(PDO::FETCH_ASSOC); 73 | $stmt = null; 74 | 75 | // Use PHP 5.5's password_verify() function to check if the provided password equals hash of the administrator's password 76 | if (password_verify($_POST['user_oldpassword'], $user['password'])) { 77 | $user_newpassword_hash = password_hash($_POST['user_newpassword'], PASSWORD_DEFAULT); 78 | 79 | // Send the prepared statement to the database 80 | $stmt = $this->db_connection->prepare('UPDATE localusers SET password = ? WHERE username = ?'); 81 | 82 | // If the administrator's password update successfully, then close the database connection and let the adminsitrator know 83 | if ($stmt->execute(array($user_newpassword_hash, $_SESSION['user_name']))) { 84 | //Close the connection 85 | $stmt = null; 86 | Logger::log ('audit', 'Local Admin Password Change: The local administrator "' . $_SESSION['user_name'] . '" successfully changed their password'); 87 | FlashMessage::flash('ChangePWMessage', 'Your password was changed successfully.'); 88 | header('Location: /settings/localusersettings.php'); 89 | exit(); 90 | } 91 | // If the adminsitrator's password update failed, then close the database connection and let the administrator know 92 | else { 93 | //Close the connection 94 | $stmt = null; 95 | Logger::log ('error', 'Password change for the local administrator "' . $SESSION['user_name'] . '" failed because the database couldn\'t execute the query'); 96 | $this->setErrorAndQuit('Sorry, your password update failed. Please go back and try again.'); 97 | } 98 | } 99 | else { 100 | Logger::log ('audit', 'Local Admin Password Change Failure: The local administrator "' . $_SESSION['user_name'] . '" failed to change their password because the current password supplied was incorrect'); 101 | // If the adminsitrator's password was incorrectly entered and let the administrator know 102 | $this->setErrorAndQuit('The password entered is incorrect.
    Please try again.'); 103 | } 104 | } 105 | 106 | else { 107 | Logger::log ('error', 'The local administrator password change failed because the user "' . $_SESSION['user_name'] . '" does not exist in the database'); 108 | $this->setErrorAndQuit('The user does not exist in the database.
    Please logout and log back in.'); 109 | } 110 | } 111 | else { 112 | Logger::log ('error', 'The local administrator password change failed for user "' . $_SESSION['user_name'] . '" because the database connection failed'); 113 | $this->setErrorAndQuit('There was a problem connecting to the database.
    Please try again.'); 114 | } 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /docs/Windows Server 2012 R2 Installation Guide.md: -------------------------------------------------------------------------------- 1 | # ADReset Documentation 2 | 3 | ## Installing ADReset on Windows Server 2012 R2 4 | 5 | ### Prerequisites 6 | 1. Windows Server 2012 R2 with: 7 | * Administrative access 8 | * "IE Enhanced Security" disabled for the installation (it can be reenabled afterwards) 9 | * Visual C++ Redistributable for Visual Studio 2012 Update 4 (x86) installed (Download x86 Version Here) 10 | * DNS configured to point to at least one Domain Controller (optional) 11 | * At least one Domain Controller with LDAPS enabled (Admin access to the Domain Controller maybe required) 12 | 13 | ### Installing IIS, PHP, and MySQL 14 |
      15 |
    1. Open "Server Manager" => Click on "Manage" => Click on "Add Roles and Features"
    2. 16 |
    3. In the "Add Roles and Features Wizard", click "Next" => Click "Next" => Click "Next" => Check "Web Server (IIS) => If a windows pops up asking "Add features that are required for Web Server (IIS)?", click "Add Features" => Click "Next"
    4. 17 |
    5. When asked to "Select features", check ".NET Framework 3.5 Features" => Click "Next" => Click "Next" => Click "Next" => Click "Install"
    6. 18 |
    7. Once IIS and .NET Framework 3.5 is installed, you may close the "Add Roles and Features Wizard" window and close "Server Manager"
    8. 19 |
    9. Download and install the "Microsoft Web Platform Installer" from here
    10. 20 |
    11. Open "Microsoft Web Platform Installer" => Search for "PHP 5.5" => Click on "Add" button in the row for "PHP 5.5" => Click on "Install" => On the pop-up Window, click "I Accept" => Once installed, click on "Finish".
    12. 21 |
    13. In "Microsoft Web Platform Installer" => Search for "MySQL 5.5" => Click on "Add" button in the row for "MySQL Windows 5.5" => Click on "Install" => On the pop-up Window, type in a root password for MySQL => Uncheck "Save my password" => Click on "Continue" => Click on "I Accept" => Once installed, click on "Finish" => Close "Web Platform Installer"
    14. 22 |
    23 | 24 | ### Downloading ADReset and Granting the Proper Permissions 25 |
      26 |
    1. Download and install "git for Windows" from http://msysgit.github.io/ (git is used to download and update ADReset)
    2. 27 |
    3. Run "Git GUI" as an Administrator => Click on "Clone Existing Repository" => Enter "https://github.com/PrahlM93/ADReset.git" for the "Source Location" => Enter "C:/inetpub/adreset" as the "Target Directory" => Click on "Clone" => Close "Git GUI"
    4. 28 |
    5. Browse to "C:\inetpub\adreset\resources" => Right-click on "core" => Click on "Properties" => Click on the "Security" tab => Click on "Edit" => In the "Permissions for core" window, click on "Add" => In the "Enter the object names to select" field, type "iusr" => Click on "Check Names" (if this doesn't work, ensure the location for the search is the local server and not Active Directory) => Click on "OK" => Check "Modify" for "IUSR" => Click on "OK" => Click on "OK".
    6. 29 |
    7. Browse to "C:\inetpub\adreset\resources" => Right-click on "logs" => Click on "Properties" => Click on the "Security" tab => Click on "Edit" => In the "Permissions for logs" window, click on "Add" => In the "Enter the object names to select" field, type "iusr" => Click on "Check Names" (if this doesn't work, ensure the location for the search is the local server and Active Directory) => Click on "OK" => Check "Modify" for "IUSR" => Click on "OK" => Click on "OK".
    8. 30 |
    31 | 32 | ### Configuring IIS and PHP 33 | 34 |
      35 |
    1. Open "Internet Information Services (IIS) Manager" => Click on your Server Name in the left pane => Double-click on "PHP Manager" => Click on "Enable or disable an extension" => Select on "php_ldap.dll" => Click on "Enable" in the "Actions" pane.
    2. 36 |
    3. In the left pane, expand "Sites" => right-click on "Default Web Site" => Hover on "Manage Website" => Click on "Advanced Settings"
    4. 37 |
    5. In the "Advanced Settings" windows, change "Physical Path" to "%SystemDrive%\inetpub\adreset\public" => Click on "OK"
    6. 38 |
    7. Click on your Server Name in the left pane => Click on "Restart" in the Actions pane.
    8. 39 |
    40 | 41 | ### Configuring PHP LDAP 42 |
      43 |
    1. Create the folder "C:\openldap"
    2. 44 |
    3. Create the folder "C:\openldap\sysconf"
    4. 45 |
    5. In order to have ADReset communicate over LDAPS, it needs to have the appropriate Active Directory Certificate Services (ADCS) CA certificate in BASE64 format. That certificate must be exported. To do so, you can follow this this tutorial
    6. 46 |
    7. After the following the tutorial in the previous step, make sure the certificate is named "LDAPS-CA.cer" and is located in "C:\openldap\sysconf"
    8. 47 |
    9. Browse to "C:\openldap\sysconf" and create a text file called ldap.conf (make sure the extension is .conf and not .txt) => Add the following contents:
    10. 48 | 49 | TLS_REQCERT never 50 |
      51 | 52 | TLS_CACERT C:\openldap\sysconf\LDAPS-CA.cer 53 | 54 |
    55 | 56 | ### Configure MySQL 57 |
      58 |
    1. Open "MySQL 5.5 Command Line Client" => Enter the root password for MySQL set earlier => Then enter the following commands (change password to a strong password):
    2. 59 | 60 | CREATE DATABASE IF NOT EXISTS adreset; 61 |
      62 | 63 | CREATE USER 'adresetuser'@'127.0.0.1' IDENTIFIED BY 'password'; 64 |
      65 | 66 | GRANT ALL PRIVILEGES ON adreset.* TO 'adresetuser'@'127.0.0.1'; 67 |
      68 | 69 | FLUSH PRIVILEGES; 70 |
      71 | 72 | QUIT; 73 | 74 |
    75 | 76 | ### Configure ADReset 77 |
      78 |
    1. Open "Internet Explorer" and browse to "http://localhost/installer.php". If the IIS configuration was successful, you should be presented with the "Install ADReset" page. (Note: The server version of Internet Explorer does not correctly render padding on forms)
    2. 79 |
    3. On this page, it will make sure you have all the PHP modules that are required. If any are missing, go back to the section “Installing Apache, MySQL, and PHP”. If you followed the directions correctly, you should see a screen that looks like this:

      80 | 81 |
    4. 82 | 83 |
    5. Now enter the settings you configured in step 2. It should look something like this:

      84 | 85 |
    6. 86 | 87 |
    7. Once the form is filled out, click on “Connect”
    8. 88 | 89 |
    9. Afterwards, you must create a local administrator account to initially configure ADReset. Here is an example:

      90 | 91 |
    10. 92 | 93 |
    11. Once the form is filled out, click on “Create”
    12. 94 | 95 |
    13. If successful, you should see the following message:

      96 | 97 |
    14. 98 | 99 |
    15. Go back to your command-line shell on Ubuntu and delete installer.php with the following command:
    16. 100 | 101 | sudo rm /var/www/adreset/public/installer.php 102 | 103 | 104 |
    17. Go back to ADReset and login with your new Administrator account.
    18. 105 | 106 |
    19. Upon login, you should be taken to the “Connection Settings” page. Here you will specify how to connect to Active Directory. Here is an example where sky.local is the domain:

      107 | 108 |
    20. 109 | 110 |
    21. Make sure that the Domain Controller you specify has LDAPS enabled. If all of your Domain Controllers have LDAPS enabled, it is recommended to put the domain name in the Domain Controller field (i.e. sky.local) as this will allow ADReset to connect to any available Domain Controller.
    22. 111 | 112 |
    23. If the connection was successful, you will receive the following message:

      113 | 114 |
    24. 115 | 116 |
    25. Now, it is time configure the System Settings, to do so, click on “Manage” then click on “System Settings”
    26. 117 |
    118 | -------------------------------------------------------------------------------- /resources/classes/NewLocalAdmin.php: -------------------------------------------------------------------------------- 1 | db_connection = startPDOConnection()) { 14 | echo '

    Database Connection Error:

    Please contact the Help Desk with this error.

    '; 15 | Logger::log('error', 'The database connection failed'); 16 | die(); 17 | } 18 | } 19 | 20 | protected function setErrorAndQuit($message) { 21 | if (isset($message)) { 22 | FlashMessage::flash('RegisterError', $message); 23 | header('Location: /installer.php'); 24 | exit(); 25 | } 26 | } 27 | 28 | // This function handles the entire registration process. It checks all error possibilities and creates a new administrator in the database if the input passes 29 | public function registerNewUser($user_group = 1) { 30 | if (empty($_POST['user_name'])) { 31 | $this->setErrorAndQuit('Username cannot be empty.'); 32 | } 33 | elseif (empty($_POST['user_password_new']) || empty($_POST['user_password_repeat'])) { 34 | $this->setErrorAndQuit('Password cannot be empty.'); 35 | } 36 | elseif ($_POST['user_password_new'] !== $_POST['user_password_repeat']) { 37 | $this->setErrorAndQuit('Passwords do not match.'); 38 | } 39 | elseif (!passwordPolicyMatch($_POST['user_password_new'])) { 40 | $this->setErrorAndQuit('Password does not conform to the password policy.
    '. passwordPolicyWritten()); 41 | } 42 | elseif (strlen($_POST['user_name']) > 64 || strlen($_POST['user_name']) < 2) { 43 | $this->setErrorAndQuit('Password does not conform to the password policy.
    '. passwordPolicyWritten()); 44 | } 45 | elseif (!preg_match('/^[a-zA-Z0-9]*[_.-]?[a-zA-Z0-9]*$/', $_POST['user_name'])) { 46 | $this->setErrorAndQuit('Username does not match the naming scheme. Only letters, numbers, underscores, and periods are allowed'); 47 | } 48 | elseif (empty($_POST['user_email'])) { 49 | $this->setErrorAndQuit('Email cannot be empty.'); 50 | } 51 | elseif (strlen($_POST['user_email']) > 64) { 52 | $this->setErrorAndQuit('Email cannot be longer than 64 characters.'); 53 | } 54 | elseif (!filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL)) { 55 | $this->setErrorAndQuit('Your email address is not in a valid email format.'); 56 | } 57 | elseif (!empty($_POST['user_name']) 58 | && strlen($_POST['user_name']) <= 64 59 | && strlen($_POST['user_name']) >= 2 60 | && preg_match('/^[a-zA-Z0-9]*[_.-]?[a-zA-Z0-9]*$/', $_POST['user_name']) 61 | && !empty($_POST['user_email']) 62 | && strlen($_POST['user_email']) <= 64 63 | && filter_var($_POST['user_email'], FILTER_VALIDATE_EMAIL) 64 | && !empty($_POST['user_password_new']) 65 | && !empty($_POST['user_password_repeat']) 66 | && ($_POST['user_password_new'] === $_POST['user_password_repeat']) 67 | ) { 68 | if ($this->db_connection = startPDOConnection()) { 69 | 70 | //Trim the whitespace 71 | $user_name = trim($_POST['user_name']); 72 | $user_fullname = trim($_POST['user_fullname']); 73 | $user_email = trim($_POST['user_email']); 74 | $user_password = $_POST['user_password_new']; 75 | $user_created = date('Y-m-d H:i:s'); 76 | 77 | // crypt the user's password with PHP 5.5's password_hash() function 78 | $user_password_hash = password_hash($user_password, PASSWORD_DEFAULT); 79 | 80 | // Check if the user/email address is already taken or not 81 | if ($stmt = $this->db_connection->prepare('SELECT null FROM localusers WHERE username=? OR email=?')) { 82 | 83 | if ($stmt->execute(array($user_name, $user_email))) { 84 | // Make sure that the user does not exist 85 | if ($stmt->rowCount() != 0) { 86 | $this->setErrorAndQuit('Sorry, that username or email address is already taken.'); 87 | } 88 | else { 89 | $stmt = null; 90 | // Prepare and bind the database to insert the administrator account 91 | if ($stmt = $this->db_connection->prepare('INSERT INTO localusers (username, password, email, name, created) VALUES (?, ?, ?, ?, ?)')) { 92 | 93 | if ($stmt->execute(array($user_name, $user_password_hash, $user_email, $user_fullname, $user_created))) { 94 | $stmt = null; 95 | Logger::log('audit', 'New Local Admin Success: The local administrator "' . $user_name . '" was created'); 96 | FlashMessage::flash('RegisterSuccess', $user_name . ' has been created successfully.
    Make sure that you delete public/installer.php.'); 97 | header('Location: /localadmin.php'); 98 | exit(); 99 | } 100 | else { 101 | $stmt = null; 102 | Logger::log('error', 'The local administrator "' . $user_name . '" could not be created due to a database error'); 103 | $this->setErrorAndQuit('Sorry, the new account creation failed.
    Please go back and try again.'); 104 | } 105 | } 106 | else { 107 | Logger::log('error', 'The local administrator "' . $user_name . '" could not be created due to a database error'); 108 | $this->setErrorAndQuit('Sorry, the new account creation failed.
    Please go back and try again.'); 109 | } 110 | } 111 | } 112 | else { 113 | Logger::log('error', 'The local administrator "' . $user_name . '" could not be created due to a database error'); 114 | $this->setErrorAndQuit('There was a problem connecting to the database.
    Please try again.'); 115 | } 116 | } 117 | else { 118 | Logger::log('error', 'The local administrator "' . $user_name . '" could not be created due to a database error'); 119 | $this->setErrorAndQuit('There was a problem connecting to the database.
    Please try again.'); 120 | } 121 | } 122 | else { 123 | Logger::log('error', 'The database connection failed'); 124 | $this->setErrorAndQuit('There was a problem connecting to the database.
    Please try again.'); 125 | } 126 | } 127 | else { 128 | $this->setErrorAndQuit('Sorry, your registration failed.
    Please go back and try again.'); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /public/js/bootbox.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * bootbox.js v4.4.0 3 | * 4 | * http://bootboxjs.com/license.txt 5 | */ 6 | !function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d.call(c,a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
    ",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
    ",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:"static",animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback.call(this):!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,!1)},a.buttons.confirm.callback=function(){return a.callback.call(this,!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback.call(this,null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback.call(this,c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!b.isArray(k))throw new Error("Please pass an array of input options");if(!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
    "),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),a.maxlength&&h.attr("maxlength",a.maxlength),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var d=b(n.dialog),f=d.find(".modal-dialog"),i=d.find(".modal-body"),j=a.buttons,k="",l={onEscape:a.onEscape};if(b.fn.modal===c)throw new Error("$.fn.modal is not defined; please double check you have included the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ for more details.");if(g(j,function(a,b){k+="",l[a]=b.callback}),i.find(".bootbox-body").html(a.message),a.animate===!0&&d.addClass("fade"),a.className&&d.addClass(a.className),"large"===a.size?f.addClass("modal-lg"):"small"===a.size&&f.addClass("modal-sm"),a.title&&i.before(n.header),a.closeButton){var m=b(n.closeButton);a.title?d.find(".modal-header").prepend(m):m.css("margin-top","-10px").prependTo(i)}return a.title&&d.find(".modal-title").html(a.title),k.length&&(i.after(n.footer),d.find(".modal-footer").html(k)),d.on("hidden.bs.modal",function(a){a.target===this&&d.remove()}),d.on("shown.bs.modal",function(){d.find(".btn-primary:first").focus()}),"static"!==a.backdrop&&d.on("click.dismiss.bs.modal",function(a){d.children(".modal-backdrop").length&&(a.currentTarget=d.children(".modal-backdrop").get(0)),a.target===a.currentTarget&&d.trigger("escape.close.bb")}),d.on("escape.close.bb",function(a){l.onEscape&&e(a,d,l.onEscape)}),d.on("click",".modal-footer button",function(a){var c=b(this).data("bb-handler");e(a,d,l[c])}),d.on("click",".bootbox-close-button",function(a){e(a,d,l.onEscape)}),d.on("keyup",function(a){27===a.which&&d.trigger("escape.close.bb")}),b(a.container).append(d),d.modal({backdrop:a.backdrop?"static":!1,keyboard:!1,show:!1}),a.show&&d.modal("show"),d},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={bg_BG:{OK:"Ок",CANCEL:"Отказ",CONFIRM:"Потвърждавам"},br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fa:{OK:"قبول",CANCEL:"لغو",CONFIRM:"تایید"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},hu:{OK:"OK",CANCEL:"Mégsem",CONFIRM:"Megerősít"},hr:{OK:"OK",CANCEL:"Odustani",CONFIRM:"Potvrdi"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sq:{OK:"OK",CANCEL:"Anulo",CONFIRM:"Prano"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},th:{OK:"ตกลง",CANCEL:"ยกเลิก",CONFIRM:"ยืนยัน"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.addLocale=function(a,c){return b.each(["OK","CANCEL","CONFIRM"],function(a,b){if(!c[b])throw new Error("Please supply a translation for '"+b+"'")}),q[a]={OK:c.OK,CANCEL:c.CANCEL,CONFIRM:c.CONFIRM},p},p.removeLocale=function(a){return delete q[a],p},p.setLocale=function(a){return p.setDefaults("locale",a)},p.init=function(c){return a(c||b)},p}); -------------------------------------------------------------------------------- /resources/classes/ADLogin.php: -------------------------------------------------------------------------------- 1 | getConnectionSettings()) { 13 | echo '

    Active Directory Connection Settings Error:

    Please contact the Help Desk with this error.

    '; 14 | Logger::log ('error', 'The database could not retrieve the connection settings for Active Directory'); 15 | exit(); 16 | } 17 | 18 | // Create or read the session 19 | @session_start(); 20 | 21 | // If the user is currently logged in as local, log them out 22 | if (isset($_SESSION['auth_source'])) { 23 | if ($_SESSION['auth_source'] == 'local') { 24 | $this->logout(); 25 | } 26 | } 27 | 28 | // Check the to see if the user is trying to log in or off 29 | if (isset($_GET["logout"])) { 30 | $this->logout(); 31 | } 32 | // If the login form was submitted, then call the doLoginWithPostData function 33 | elseif (isset($_POST["login"])) { 34 | $this->loginWithPOST(); 35 | } 36 | } 37 | 38 | public function __destruct() { 39 | //Close the AD connection on destruction 40 | @ldap_unbind($this->ad_connection); 41 | } 42 | 43 | private function getConnectionSettings() { 44 | $connectionSettingsObject = new ConnectionSettings(); 45 | // Just get the settings we need to login as a user supplied by POST 46 | $this->connectionSettings['DC'] = $connectionSettingsObject->get('DC'); 47 | $this->connectionSettings['port'] = $connectionSettingsObject->get('port'); 48 | $this->connectionSettings['domainName'] = $connectionSettingsObject->get('domainName'); 49 | // Make sure all the settings are set, otherwise we don't want anyone to be able to login 50 | if (!empty($this->connectionSettings) && $connectionSettingsObject->areAllSettingsSet()) { 51 | return true; 52 | } 53 | // default return 54 | return false; 55 | } 56 | 57 | private function connect() { 58 | if (isset($this->connectionSettings['DC']) && isset($this->connectionSettings['port'])) { 59 | if ($this->ad_connection = ldap_connect($this->connectionSettings['DC'], $this->connectionSettings['port'])) { 60 | return true; 61 | } 62 | } 63 | 64 | return false; 65 | } 66 | 67 | private function bind($username, $password) { 68 | if (isset($username) && isset($password)) { 69 | ldap_set_option($this->ad_connection, LDAP_OPT_PROTOCOL_VERSION, 3); 70 | ldap_set_option($this->ad_connection, LDAP_OPT_REFERRALS, 0); 71 | 72 | $ldapUsername = $username; 73 | // If they entered username@domain.local, remove the @domain.local 74 | $ldapUsername = preg_replace('{@.*$}', '' , $ldapUsername); 75 | // If they entered domain\username, then remove domain\ 76 | $ldapUsername = preg_replace('{^.*\\\}', '' , $ldapUsername); 77 | // Add the @domain.local 78 | $ldapUsername = $ldapUsername . '@' . $this->connectionSettings['domainName']; 79 | 80 | if (@ldap_bind( $this->ad_connection, $ldapUsername, $password )) { 81 | return true; 82 | } 83 | else { 84 | return false; 85 | } 86 | } 87 | 88 | else { 89 | return false; 90 | } 91 | } 92 | 93 | 94 | public function isUserAdmin($username) { 95 | if (isset($username)) { 96 | if ($systemSettings = new SystemSettings()) { 97 | if ($adminGroups = $systemSettings->getAdminGroups()) { 98 | try { 99 | $AD = new AD(); 100 | $userGroups = $AD->getMembership($username); 101 | foreach ($userGroups as $userGroup) { 102 | foreach ($adminGroups as $adminGroup) { 103 | if ($userGroup == $adminGroup['samaccountname']) { 104 | return true; 105 | } 106 | } 107 | } 108 | } 109 | catch(Exception $e) { 110 | Logger::log('error', $e . ' when attempting to check the user membership of ' . $username); 111 | return false; 112 | } 113 | } 114 | } 115 | } 116 | 117 | return false; 118 | } 119 | 120 | private function setLoginErrorAndQuit($message) { 121 | if (isset($message)) { 122 | FlashMessage::flash('LoginError', $message); 123 | if (isset($_GET['page'])){ 124 | header('Location: /account.php?page=' . $_GET['page']); 125 | } 126 | else { 127 | header('Location: /account.php'); 128 | } 129 | exit(); 130 | } 131 | } 132 | 133 | private function loginWithPOST() { 134 | // Verfiy the contents that were submitted by the form 135 | if (empty($_POST['user_name'])) { 136 | FlashMessage::flash('LoginError', 'The Username field was empty.'); 137 | header('Location: /account.php'); 138 | exit(); 139 | } 140 | elseif (empty($_POST['user_password'])) { 141 | FlashMessage::flash('LoginError', 'The Password field was empty.'); 142 | header('Location: /account.php'); 143 | exit(); 144 | } 145 | elseif (!empty($_POST['user_name']) && !empty($_POST['user_password'])) { 146 | // Trimming the whitespace. 147 | $user_name = trim($_POST['user_name']); 148 | $user_password = trim($_POST['user_password']); 149 | // Start the AD connection 150 | if ($this->connect()) { 151 | if ($this->bind($user_name, $user_password)) { 152 | // Create a ResetPW object to gain access to the isUserAllowedToReset function. 153 | $resetPW = new ResetPW(); 154 | $AD = new AD(); 155 | 156 | // Write the user's data into a PHP SESSION 157 | // Determine the user's privilege level 158 | if ($this->isUserAdmin($user_name)) { 159 | $_SESSION['privilege'] = 'admin'; 160 | } 161 | elseif ($resetPW->isUserAllowedToReset($user_name, $AD)) { 162 | $_SESSION['privilege'] = 'user'; 163 | } 164 | else { 165 | $this->setLoginErrorAndQuit('You do not have permission to use ADReset. Please contact the Help Desk for assistance.'); 166 | } 167 | 168 | $_SESSION['user_name'] = $user_name; 169 | $_SESSION['auth_source'] = 'domain'; 170 | $_SESSION['user_login_status'] = 1; 171 | 172 | Logger::log ('audit', 'Login Success: The user "' . $user_name . '"" logged in'); 173 | 174 | // If the page GET variable was set, then redirect the user to that page after logging in 175 | if (isset($_GET['page'])){ 176 | header('Location: /' . urldecode($_GET['page'])); 177 | } 178 | else { 179 | header('Location: /account.php'); 180 | } 181 | exit(); 182 | } 183 | // If the username or password is incorrect, notify the user trying to log in 184 | else { 185 | // If the DC is not available, let the user know so they can contact Help Desk 186 | if (ldap_error($this->ad_connection) == 'Can\'t contact LDAP server') { 187 | Logger::log ('error', 'The Domain Controller could not be contacted'); 188 | $this->setLoginErrorAndQuit('The Domain Controller could not be contacted.
    Please try again.'); 189 | } 190 | elseif (ldap_error($this->ad_connection) == 'Invalid credentials') { 191 | Logger::log ('audit', 'Login Failure: The username or password is incorrect for the user "' . $user_name . '"'); 192 | $this->setLoginErrorAndQuit('The Username or Password is incorrect. Please try again.'); 193 | } 194 | else { 195 | Logger::log ('error', 'The following error occured when "' . $user_name . '"" attempted to login: ' . ldap_error($this->ad_connection)); 196 | $this->setLoginErrorAndQuit('The Username or Password is incorrect. Please try again.'); 197 | } 198 | } 199 | } 200 | // If the AD connection fails, notify the user trying to log in 201 | else { 202 | Logger::log ('error', 'The Domain Controller could not be contacted'); 203 | $this->setLoginErrorAndQuit('There was a problem connecting to the Domain Controller. Please try again.'); 204 | } 205 | } 206 | } 207 | 208 | public function logout() { 209 | if (isset($_SESSION['user_name'])) { 210 | Logger::log ('audit', 'Logout Success: The user "' . $_SESSION['user_name'] . '" logged out'); 211 | } 212 | 213 | // If the page GET request was set, then redirect them to that page after log out. If not, redirect them to the homepage. 214 | if (isset($_GET['page'])) { 215 | 216 | $page = $_GET['page']; 217 | 218 | // Delete the user's session 219 | $_SESSION = array(); 220 | session_destroy(); 221 | header('Location: /' . $page); 222 | } 223 | else { 224 | // Delete the user's session 225 | $_SESSION = array(); 226 | session_destroy(); 227 | header('Location: /index.php'); 228 | } 229 | exit(); 230 | } 231 | 232 | public function isUserLoggedIn() { 233 | if (isset($_SESSION['user_login_status']) AND $_SESSION['user_login_status'] == 1) { 234 | return true; 235 | } 236 | // default return 237 | return false; 238 | } 239 | } 240 | --------------------------------------------------------------------------------