diff --git a/action.php b/action.php index a6a50ab..13bd694 100644 --- a/action.php +++ b/action.php @@ -3,10 +3,14 @@ /** * Make things happen when buttons are pressed and forms submitted. */ +use LdapTools\LdapManager; +use LdapTools\Object\LdapObjectType; + require_once __DIR__ . "/required.php"; dieifnotloggedin(); +require_once __DIR__ . "/lib/login.php"; require_once __DIR__ . "/lib/worst_passwords.php"; function returnToSender($msg, $arg = "") { @@ -21,12 +25,12 @@ function returnToSender($msg, $arg = "") { switch ($VARS['action']) { case "signout": + insertAuthLog(11, $_SESSION['uid']); session_destroy(); header('Location: index.php'); die("Logged out."); case "chpasswd": - $oldmatch = comparePassword($VARS['oldpass'], $database->select('accounts', 'password', ['uid' => $_SESSION['uid']])[0]); - if ($oldmatch) { + if ($_SESSION['password'] == $VARS['oldpass']) { if ($VARS['newpass'] == $VARS['conpass']) { $passrank = checkWorst500List($VARS['newpass']); if ($passrank !== FALSE) { @@ -35,8 +39,29 @@ switch ($VARS['action']) { if (strlen($VARS['newpass']) < MIN_PASSWORD_LENGTH) { returnToSender("weak_password"); } - $database->update('accounts', ['password' => encryptPassword($VARS['newpass'])], ['uid' => $_SESSION['uid']]); - returnToSender("password_updated"); + + $acctloc = account_location($_SESSION['username'], $_SESSION['password']); + + if ($acctloc == "LOCAL") { + $database->update('accounts', ['password' => encryptPassword($VARS['newpass'])], ['uid' => $_SESSION['uid']]); + $_SESSION['password'] = $VARS['newpass']; + insertAuthLog(3, $_SESSION['uid']); + returnToSender("password_updated"); + } else if ($acctloc == "LDAP") { + $ldapManager = new LdapManager($ldap_config); + $repository = $ldapManager->getRepository(LdapObjectType::USER); + $user = $repository->findOneByUsername($_SESSION['username']); + $user->setPassword($VARS['newpass']); + try { + $ldapManager->persist($user); + insertAuthLog(3, $_SESSION['uid']); + returnToSender("password_updated"); + } catch (\Exception $e) { + returnToSender("ldap_error", $e->getMessage()); + } + } else { + returnToSender("account_state_error"); + } } else { returnToSender("new_password_mismatch"); } @@ -49,9 +74,11 @@ switch ($VARS['action']) { returnToSender("invalid_parameters"); } $database->update('accounts', ['authsecret' => $VARS['secret']], ['uid' => $_SESSION['uid']]); + insertAuthLog(9, $_SESSION['uid']); returnToSender("2fa_enabled"); case "rm2fa": $database->update('accounts', ['authsecret' => ""], ['uid' => $_SESSION['uid']]); + insertAuthLog(10, $_SESSION['uid']); returnToSender("2fa_removed"); break; } \ No newline at end of file diff --git a/api.php b/api.php new file mode 100644 index 0000000..6bdf63d --- /dev/null +++ b/api.php @@ -0,0 +1,119 @@ +has('apikeys', ['key' => $key]) !== TRUE) { + header("HTTP/1.1 403 Unauthorized"); + die("\"403 Unauthorized\""); +} + +switch ($VARS['action']) { + case "ping": + exit(json_encode(["status" => "OK"])); + break; + case "auth": + if (authenticate_user($VARS['username'], $VARS['password'])) { + insertAuthLog(12); + exit(json_encode(["status" => "OK", "msg" => lang("login successful", false)])); + } else { + insertAuthLog(13); + exit(json_encode(["status" => "ERROR", "msg" => lang("login incorrect", false)])); + } + break; + case "userinfo": + if (user_exists($VARS['username'])) { + $data = $database->select("accounts", ["uid", "realname (name)", "email", "phone" => ["phone1 (1)", "phone2 (2)"]], ["username" => $VARS['username']])[0]; + exit(json_encode(["status" => "OK", "data" => $data])); + } else { + exit(json_encode(["status" => "ERROR", "msg" => lang("login incorrect", false)])); + } + break; + case "userexists": + if (user_exists($VARS['username'])) { + exit(json_encode(["status" => "OK", "exists" => true])); + } else { + exit(json_encode(["status" => "OK", "exists" => false])); + } + break; + case "hastotp": + if (userHasTOTP($VARS['username'])) { + exit(json_encode(["status" => "OK", "otp" => true])); + } else { + exit(json_encode(["status" => "OK", "otp" => false])); + } + break; + case "verifytotp": + if (verifyTOTP($VARS['username'], $VARS['code'])) { + exit(json_encode(["status" => "OK", "valid" => true])); + } else { + insertAuthLog(7); + exit(json_encode(["status" => "ERROR", "msg" => lang("2fa incorrect", false), "valid" => false])); + } + break; + case "acctstatus": + exit(json_encode(["status" => "OK", "account" => get_account_status($VARS['username'])])); + case "login": + // simulate a login, checking account status and alerts + if (authenticate_user($VARS['username'], $VARS['password'])) { + switch (get_account_status($VARS['username'])) { + case "LOCKED_OR_DISABLED": + insertAuthLog(5); + exit(json_encode(["status" => "ERROR", "msg" => lang("account locked", false)])); + case "TERMINATED": + insertAuthLog(5); + exit(json_encode(["status" => "ERROR", "msg" => lang("account terminated", false)])); + case "CHANGE_PASSWORD": + insertAuthLog(5); + exit(json_encode(["status" => "ERROR", "msg" => lang("password expired", false)])); + case "NORMAL": + insertAuthLog(4); + exit(json_encode(["status" => "OK"])); + case "ALERT_ON_ACCESS": + sendLoginAlertEmail($VARS['username']); + insertAuthLog(4); + exit(json_encode(["status" => "OK", "alert" => true])); + default: + insertAuthLog(5); + exit(json_encode(["status" => "ERROR", "msg" => lang("account state error", false)])); + } + } else { + insertAuthLog(5); + exit(json_encode(["status" => "ERROR", "msg" => lang("login incorrect", false)])); + } + break; + case "ismanagerof": + if (user_exists($VARS['manager'])) { + if (user_exists($VARS['employee'])) { + $managerid = $database->select('accounts', 'uid', ['username' => $VARS['manager']]); + $employeeid = $database->select('accounts', 'uid', ['username' => $VARS['employee']]); + if ($database->has('managers', ['AND' => ['managerid' => $managerid, 'employeeid' => $employeeid]])) { + exit(json_encode(["status" => "OK", "managerof" => true])); + } else { + exit(json_encode(["status" => "OK", "managerof" => false])); + } + } else { + exit(json_encode(["status" => "ERROR", "msg" => lang("user does not exist", false), "user" => $VARS['employee']])); + } + } else { + exit(json_encode(["status" => "ERROR", "msg" => lang("user does not exist", false), "user" => $VARS['manager']])); + } + break; + default: + header("HTTP/1.1 400 Bad Request"); + die("\"400 Bad Request\""); +} + /* } catch (Exception $e) { + header("HTTP/1.1 500 Internal Server Error"); + die("\"500 Internal Server Error\""); + } */ \ No newline at end of file diff --git a/composer.json b/composer.json index cf35bd3..23298f4 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,9 @@ "require": { "catfan/medoo": "^1.2", "spomky-labs/otphp": "^8.3", - "endroid/qrcode": "^1.9" + "endroid/qrcode": "^1.9", + "ldaptools/ldaptools": "^0.24.0", + "guzzlehttp/guzzle": "^6.2" }, "authors": [ { diff --git a/composer.lock b/composer.lock index 7a21db0..76e01a1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "3d5a548f8a7cbbd0c911987b1fab33a5", + "content-hash": "4965262916e04d361db07e7f14ed06d6", "packages": [ { "name": "beberlei/assert", @@ -230,6 +230,244 @@ ], "time": "2017-04-08T09:13:59+00:00" }, + { + "name": "guzzlehttp/guzzle", + "version": "6.2.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2017-02-28T22:50:30+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, + { + "name": "ldaptools/ldaptools", + "version": "v0.24.0", + "source": { + "type": "git", + "url": "https://github.com/ldaptools/ldaptools.git", + "reference": "31e05ae6082fc7e61afc666e2c773ee8cb0e47b5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ldaptools/ldaptools/zipball/31e05ae6082fc7e61afc666e2c773ee8cb0e47b5", + "reference": "31e05ae6082fc7e61afc666e2c773ee8cb0e47b5", + "shasum": "" + }, + "require": { + "ext-ldap": "*", + "php": ">=5.6", + "ramsey/uuid": ">=3.0", + "symfony/event-dispatcher": ">=2.0", + "symfony/yaml": ">=2.0" + }, + "require-dev": { + "doctrine/cache": "~1.0", + "friendsofphp/php-cs-fixer": "~1.0", + "phpspec/phpspec": "~3.0", + "tedivm/stash": ">=0.14.1" + }, + "suggest": { + "doctrine/cache": "Provides the cache_type 'doctrine' to help increase performance.", + "ext-intl": "Better UTF-8 handling.", + "ext-mbstring": "Better UTF-8 handling.", + "tedivm/stash": "Provides the cache_type 'stash' to help increase performance." + }, + "type": "library", + "autoload": { + "psr-4": { + "LdapTools\\": "src/LdapTools" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Chad Sikorra", + "email": "Chad.Sikorra@gmail.com", + "homepage": "http://www.chadsikorra.com" + } + ], + "description": "LdapTools is a feature-rich LDAP library for PHP 5.6+.", + "homepage": "http://www.phpldaptools.com", + "keywords": [ + "Microsoft Exchange", + "active directory", + "ldap", + "openldap" + ], + "time": "2017-04-09T23:39:51+00:00" + }, { "name": "paragonie/random_compat", "version": "v2.0.10", @@ -278,6 +516,138 @@ ], "time": "2017-03-13T16:27:32+00:00" }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ramsey/uuid", + "version": "3.6.1", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "4ae32dd9ab8860a4bbd750ad269cba7f06f7934e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/4ae32dd9ab8860a4bbd750ad269cba7f06f7934e", + "reference": "4ae32dd9ab8860a4bbd750ad269cba7f06f7934e", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "^1.0|^2.0", + "php": "^5.4 || ^7.0" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "apigen/apigen": "^4.1", + "codeception/aspect-mock": "^1.0 | ^2.0", + "doctrine/annotations": "~1.2.0", + "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ^2.1", + "ircmaxell/random-lib": "^1.1", + "jakub-onderka/php-parallel-lint": "^0.9.0", + "mockery/mockery": "^0.9.4", + "moontoast/math": "^1.1", + "php-mock/php-mock-phpunit": "^0.3|^1.1", + "phpunit/phpunit": "^4.7|>=5.0 <5.4", + "satooshi/php-coveralls": "^0.6.1", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", + "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2017-03-26T20:37:53+00:00" + }, { "name": "spomky-labs/otphp", "version": "v8.3.0", @@ -342,6 +712,66 @@ ], "time": "2016-12-08T10:46:02+00:00" }, + { + "name": "symfony/event-dispatcher", + "version": "v3.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "154bb1ef7b0e42ccc792bd53edbce18ed73440ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/154bb1ef7b0e42ccc792bd53edbce18ed73440ca", + "reference": "154bb1ef7b0e42ccc792bd53edbce18ed73440ca", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0", + "symfony/expression-language": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2017-04-04T07:26:27+00:00" + }, { "name": "symfony/options-resolver", "version": "v3.2.7", @@ -562,6 +992,61 @@ "shim" ], "time": "2016-11-14T01:06:16+00:00" + }, + { + "name": "symfony/yaml", + "version": "v3.2.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/62b4cdb99d52cb1ff253c465eb1532a80cebb621", + "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2017-03-20T09:45:15+00:00" } ], "packages-dev": [], diff --git a/database.mwb b/database.mwb index 07f7edc..6c209b0 100644 Binary files a/database.mwb and b/database.mwb differ diff --git a/home.php b/home.php index e3ec221..92dd18f 100644 --- a/home.php +++ b/home.php @@ -34,7 +34,7 @@ if (!is_empty($_GET['page'])) {
- +