TODO: Test changing AD passwordstags/1.0beta
@@ -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; | |||
} |
@@ -0,0 +1,119 @@ | |||
<?php | |||
/** | |||
* Simple JSON API to allow other apps to access accounts in this system. | |||
* | |||
* Requests can be sent via either GET or POST requests. POST is recommended | |||
* as it has a lower chance of being logged on the server, exposing unencrypted | |||
* user passwords. | |||
*/ | |||
require __DIR__ . '/required.php'; | |||
require_once __DIR__ . '/lib/login.php'; | |||
header("Content-Type: application/json"); | |||
//try { | |||
$key = $VARS['key']; | |||
if ($database->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\""); | |||
} */ |
@@ -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": [ | |||
{ |
@@ -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": [], |
@@ -34,7 +34,7 @@ if (!is_empty($_GET['page'])) { | |||
<div class="container"> | |||
<div class="row"> | |||
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4"> | |||
<img class="img-responsive banner-image" src="static/img/banner.png" /> | |||
<img class="img-responsive banner-image" src="static/img/logo.svg" /> | |||
</div> | |||
</div> | |||
<nav class="navbar navbar-inverse"> | |||
@@ -130,17 +130,18 @@ END; | |||
if ($appcount == 1) { | |||
?> | |||
<div class="hidden-xs col-sm-3 col-md-4 col-lg-4"> | |||
<!-- Placeholder column for nice center-align --> | |||
<!-- Empty placeholder column for nice center-align --> | |||
</div> | |||
<?php | |||
} else if ($appcount == 2) { | |||
?> | |||
<div class="hidden-xs hidden-sm col-md-2 col-lg-2"> | |||
<!-- Placeholder column for nice center-align --> | |||
<!-- Empty placeholder column for nice center-align --> | |||
</div> | |||
<?php | |||
} | |||
// Load app widgets | |||
foreach (APPS[$pageid] as $app) { | |||
if (file_exists(__DIR__ . "/apps/" . $app . ".php")) { | |||
include_once __DIR__ . "/apps/" . $app . ".php"; |
@@ -7,43 +7,52 @@ require_once __DIR__ . "/lib/login.php"; | |||
$userpass_ok = false; | |||
$multiauth = false; | |||
if ($VARS['progress'] == "1") { | |||
if (authenticate_user($VARS['username'], $VARS['password'])) { | |||
switch (get_account_status($VARS['username'])) { | |||
case "LOCKED_OR_DISABLED": | |||
$alert = lang("account locked", false); | |||
break; | |||
case "TERMINATED": | |||
$alert = lang("account terminated", false); | |||
break; | |||
case "CHANGE_PASSWORD": | |||
$alert = lang("password expired", false); | |||
case "NORMAL": | |||
$userpass_ok = true; | |||
break; | |||
case "ALERT_ON_ACCESS": | |||
sendAlertEmail($VARS['username']); | |||
$userpass_ok = true; | |||
break; | |||
} | |||
if ($userpass_ok) { | |||
if (userHasTOTP($VARS['username'])) { | |||
$multiauth = true; | |||
} else { | |||
doLoginUser($VARS['username']); | |||
header('Location: home.php'); | |||
die("Logged in, go to home.php"); | |||
if (!RECAPTCHA_ENABLED || (RECAPTCHA_ENABLED && verifyReCaptcha($VARS['g-recaptcha-response']))) { | |||
if (authenticate_user($VARS['username'], $VARS['password'])) { | |||
switch (get_account_status($VARS['username'])) { | |||
case "LOCKED_OR_DISABLED": | |||
$alert = lang("account locked", false); | |||
break; | |||
case "TERMINATED": | |||
$alert = lang("account terminated", false); | |||
break; | |||
case "CHANGE_PASSWORD": | |||
$alert = lang("password expired", false); | |||
case "NORMAL": | |||
$userpass_ok = true; | |||
break; | |||
case "ALERT_ON_ACCESS": | |||
sendLoginAlertEmail($VARS['username']); | |||
$userpass_ok = true; | |||
break; | |||
} | |||
if ($userpass_ok) { | |||
if (userHasTOTP($VARS['username'])) { | |||
$multiauth = true; | |||
} else { | |||
doLoginUser($VARS['username'], $VARS['password']); | |||
insertAuthLog(1, $_SESSION['uid']); | |||
header('Location: home.php'); | |||
die("Logged in, go to home.php"); | |||
} | |||
} | |||
} else { | |||
$alert = lang("login incorrect", false); | |||
insertAuthLog(2); | |||
} | |||
} else { | |||
$alert = lang("login incorrect", false); | |||
$alert = lang("captcha error", false); | |||
insertAuthLog(8); | |||
} | |||
} else if ($VARS['progress'] == "2") { | |||
if (verifyTOTP($VARS['username'], $VARS['authcode'])) { | |||
doLoginUser($VARS['username']); | |||
doLoginUser($VARS['username'], $VARS['password']); | |||
insertAuthLog(1, $_SESSION['uid']); | |||
header('Location: home.php'); | |||
die("Logged in, go to home.php"); | |||
} else { | |||
$alert = lang("2fa incorrect", false); | |||
insertAuthLog(6); | |||
} | |||
} | |||
?> | |||
@@ -58,13 +67,16 @@ if ($VARS['progress'] == "1") { | |||
<link href="static/css/bootstrap.min.css" rel="stylesheet"> | |||
<link href="static/css/app.css" rel="stylesheet"> | |||
<?php if (RECAPTCHA_ENABLED) { ?> | |||
<script src='https://www.google.com/recaptcha/api.js'></script> | |||
<?php } ?> | |||
</head> | |||
<body> | |||
<div class="container"> | |||
<div class="row"> | |||
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-4 col-sm-offset-3 col-md-offset-4 col-lg-offset-4"> | |||
<div> | |||
<img class="img-responsive banner-image" src="static/img/banner.png" /> | |||
<img class="img-responsive banner-image" src="static/img/logo.svg" /> | |||
</div> | |||
<div class="panel panel-primary"> | |||
<div class="panel-heading"> | |||
@@ -85,6 +97,10 @@ if ($VARS['progress'] == "1") { | |||
?> | |||
<input type="text" class="form-control" name="username" placeholder="<?php lang("username"); ?>" required="required" autofocus /><br /> | |||
<input type="password" class="form-control" name="password" placeholder="<?php lang("password"); ?>" required="required" /><br /> | |||
<?php if (RECAPTCHA_ENABLED) { ?> | |||
<div class="g-recaptcha" data-sitekey="<?php echo RECAPTCHA_SITE_KEY; ?>"></div> | |||
<br /> | |||
<?php } ?> | |||
<input type="hidden" name="progress" value="1" /> | |||
<?php | |||
} else if ($multiauth) { |
@@ -9,9 +9,11 @@ define("STRINGS", [ | |||
"2fa prompt" => "Enter the six-digit code from your mobile authenticator app.", | |||
"2fa incorrect" => "Authentication code incorrect.", | |||
"login incorrect" => "Login incorrect.", | |||
"login successful" => "Login successful.", | |||
"account locked" => "This account has been disabled. Contact technical support.", | |||
"password expired" => "You must change your password before continuing.", | |||
"account terminated" => "Account terminated. Access denied.", | |||
"account state error" => "Your account state is not stable. Log out, restart your browser, and try again.", | |||
"password on 500 list" => "The given password is ranked number {arg} out of the 500 most common passwords. Try a different one.", | |||
"welcome user" => "Welcome, {user}!", | |||
"change password" => "Change password", | |||
@@ -36,5 +38,8 @@ define("STRINGS", [ | |||
"scan 2fa qrcode" => "Scan the QR Code with the authenticator app, or enter the secret key manually.", | |||
"confirm 2fa" => "Finish setup", | |||
"invalid parameters" => "Invalid request parameters.", | |||
"ldap server error" => "The LDAP server returned an error: {arg}", | |||
"user does not exist" => "User does not exist.", | |||
"captcha error" => "There was a problem with the CAPTCHA (robot test). Try again.", | |||
"home" => "Home", | |||
]); |
@@ -32,5 +32,13 @@ define("MESSAGES", [ | |||
"password_500" => [ | |||
"string" => "password on 500 list", | |||
"type" => "danger" | |||
], | |||
"account_state_error" => [ | |||
"string" => "account state error", | |||
"type" => "danger" | |||
], | |||
"ldap_error" => [ | |||
"string" => "ldap server error", | |||
"type" => "danger" | |||
] | |||
]); |
@@ -1,32 +1,317 @@ | |||
<?php | |||
/** | |||
* Authentication and account functions | |||
*/ | |||
use Base32\Base32; | |||
use OTPHP\TOTP; | |||
use LdapTools\LdapManager; | |||
use LdapTools\Connection\ADResponseCodes; | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// Account handling // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/** | |||
* Send an alert email to the system admin | |||
* | |||
* Used when an account with the status ALERT_ON_ACCESS logs in | |||
* @param String $username the account username | |||
* Add a user to the system. /!\ Assumes input is OK /!\ | |||
* @param string $username Username, saved in lowercase. | |||
* @param string $password Password, will be hashed before saving. | |||
* @param string $realname User's real legal name | |||
* @param string $email User's email address. | |||
* @param string $phone1 Phone number #1 | |||
* @param string $phone2 Phone number #2 | |||
* @param string $type Account type | |||
* @return int The new user's ID number in the database. | |||
*/ | |||
function sendAlertEmail($username) { | |||
// TODO: add email code | |||
function adduser($username, $password, $realname, $email = null, $phone1 = "", $phone2 = "", $type) { | |||
global $database; | |||
$database->insert('accounts', [ | |||
'username' => strtolower($username), | |||
'password' => (is_null($password) ? null : encryptPassword($password)), | |||
'realname' => $realname, | |||
'email' => $email, | |||
'phone1' => $phone1, | |||
'phone2' => $phone2, | |||
'acctstatus' => 1, | |||
'accttype' => $type | |||
]); | |||
var_dump($database->error()); | |||
return $database->id(); | |||
} | |||
/** | |||
* Get where a user's account actually is. | |||
* @param string $username | |||
* @return string "LDAP", "LOCAL", "LDAP_ONLY", or "NONE". | |||
*/ | |||
function account_location($username, $password) { | |||
global $database; | |||
$username = strtolower($username); | |||
$user_exists = user_exists($username); | |||
if (!$user_exists && !LDAP_ENABLED) { | |||
return false; | |||
} | |||
if ($user_exists) { | |||
$userinfo = $database->select('accounts', ['password'], ['username' => $username])[0]; | |||
// if password empty, it's an LDAP user | |||
if (is_empty($userinfo['password']) && LDAP_ENABLED) { | |||
return "LDAP"; | |||
} else if (is_empty($userinfo['password']) && !LDAP_ENABLED) { | |||
return "NONE"; | |||
} else { | |||
return "LOCAL"; | |||
} | |||
} else { | |||
if (user_exists_ldap($username, $password)) { | |||
return "LDAP_ONLY"; | |||
} else { | |||
return "NONE"; | |||
} | |||
} | |||
} | |||
/** | |||
* Checks the given credentials against the database. | |||
* @param string $username | |||
* @param string $password | |||
* @return boolean True if OK, else false | |||
*/ | |||
function authenticate_user($username, $password) { | |||
global $database; | |||
global $ldap_config; | |||
$username = strtolower($username); | |||
if (is_empty($username) || is_empty($password)) { | |||
return false; | |||
} | |||
$loc = account_location($username, $password); | |||
if ($loc == "NONE") { | |||
return false; | |||
} else if ($loc == "LOCAL") { | |||
$hash = $database->select('accounts', ['password'], ['username' => $username, "LIMIT" => 1])[0]['password']; | |||
return (comparePassword($password, $hash)); | |||
} else if ($loc == "LDAP") { | |||
return authenticate_user_ldap($username, $password) === TRUE; | |||
} else if ($loc == "LDAP_ONLY") { | |||
try { | |||
if (authenticate_user_ldap($username, $password) === TRUE) { | |||
$user = (new LdapManager($ldap_config))->getRepository('user')->findOneByUsername($username); | |||
//var_dump($user); | |||
adduser($user->getUsername(), null, $user->getName(), ($user->hasEmailAddress() ? $user->getEmailAddress() : null), "", "", 2); | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
} catch (Exception $e) { | |||
sendError("LDAP error: " . $e->getMessage()); | |||
} | |||
} else { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Check if a username exists in the local database. | |||
* @param String $username | |||
*/ | |||
function user_exists($username) { | |||
global $database; | |||
$username = strtolower($username); | |||
return $database->has('accounts', ['username' => $username, "LIMIT" => QUERY_LIMIT]); | |||
} | |||
/** | |||
* Get the account status: NORMAL, TERMINATED, LOCKED_OR_DISABLED, | |||
* CHANGE_PASSWORD, or ALERT_ON_ACCESS | |||
* @global $database $database | |||
* @param string $username | |||
* @return string | |||
*/ | |||
function get_account_status($username) { | |||
global $database; | |||
$username = strtolower($username); | |||
$loc = account_location($username); | |||
if ($loc == "LOCAL") { | |||
$statuscode = $database->select('accounts', [ | |||
'[>]acctstatus' => [ | |||
'acctstatus' => 'statusid' | |||
] | |||
], [ | |||
'accounts.acctstatus', | |||
'acctstatus.statuscode' | |||
], [ | |||
'username' => $username, | |||
"LIMIT" => 1 | |||
] | |||
)[0]['statuscode']; | |||
return $statuscode; | |||
} else if ($loc == "LDAP") { | |||
// TODO: Read actual account status from AD servers | |||
return "NORMAL"; | |||
} else { | |||
// account isn't setup properly | |||
return "LOCKED_OR_DISABLED"; | |||
} | |||
} | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// Login handling // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/** | |||
* Setup $_SESSION values to log in a user | |||
* @param string $username | |||
*/ | |||
function doLoginUser($username) { | |||
function doLoginUser($username, $password) { | |||
global $database; | |||
$username = strtolower($username); | |||
$userinfo = $database->select('accounts', ['email', 'uid', 'realname'], ['username' => $username])[0]; | |||
$_SESSION['username'] = $username; | |||
$_SESSION['uid'] = $userinfo['uid']; | |||
$_SESSION['email'] = $userinfo['email']; | |||
$_SESSION['realname'] = $userinfo['realname']; | |||
$_SESSION['password'] = $password; // needed for things like EWS | |||
$_SESSION['loggedin'] = true; | |||
} | |||
/** | |||
* Send an alert email to the system admin | |||
* | |||
* Used when an account with the status ALERT_ON_ACCESS logs in | |||
* @param String $username the account username | |||
*/ | |||
function sendLoginAlertEmail($username) { | |||
// TODO: add email code | |||
} | |||
function insertAuthLog($type, $uid = null) { | |||
global $database; | |||
$ip = ""; | |||
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) { | |||
$ip = $_SERVER["HTTP_CF_CONNECTING_IP"]; | |||
} else if (isset($_SERVER["HTTP_CLIENT_IP"])) { | |||
$ip = $_SERVER["HTTP_CLIENT_IP"]; | |||
} else if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) { | |||
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; | |||
} else if (isset($_SERVER["HTTP_X_FORWARDED"])) { | |||
$ip = $_SERVER["HTTP_X_FORWARDED"]; | |||
} else if (isset($_SERVER["HTTP_FORWARDED_FOR"])) { | |||
$ip = $_SERVER["HTTP_FORWARDED_FOR"]; | |||
} else if (isset($_SERVER["HTTP_FORWARDED"])) { | |||
$ip = $_SERVER["HTTP_FORWARDED"]; | |||
} else if (isset($_SERVER["REMOTE_ADDR"])) { | |||
$ip = $_SERVER["REMOTE_ADDR"]; | |||
} else { | |||
$ip = "NOT FOUND"; | |||
} | |||
$database->insert("authlog", ['#logtime' => 'NOW()', 'logtype' => $type, 'uid' => $uid, 'ip' => $ip]); | |||
} | |||
function verifyReCaptcha($response) { | |||
try { | |||
$client = new GuzzleHttp\Client(); | |||
$response = $client | |||
->request('POST', "https://www.google.com/recaptcha/api/siteverify", [ | |||
'form_params' => [ | |||
'secret' => RECAPTCHA_SECRET_KEY, | |||
'response' => $response | |||
] | |||
]); | |||
if ($response->getStatusCode() != 200) { | |||
return false; | |||
} | |||
$resp = json_decode($response->getBody(), TRUE); | |||
if ($resp['success'] === true) { | |||
return true; | |||
} else { | |||
return false; | |||
} | |||
} catch (Exception $e) { | |||
return false; | |||
} | |||
} | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// LDAP handling // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/** | |||
* Checks the given credentials against the LDAP server. | |||
* @param string $username | |||
* @param string $password | |||
* @return mixed True if OK, else false or the error code from the server | |||
*/ | |||
function authenticate_user_ldap($username, $password) { | |||
global $ldap_config; | |||
if (is_empty($username) || is_empty($password)) { | |||
return false; | |||
} | |||
$username = strtolower($username); | |||
try { | |||
$ldapManager = new LdapManager($ldap_config); | |||
$msg = ""; | |||
$code = 0; | |||
if ($ldapManager->authenticate($username, $password, $msg, $code) === TRUE) { | |||
return true; | |||
} else { | |||
return $code; | |||
} | |||
} catch (Exception $e) { | |||
sendError("LDAP error: " . $e->getMessage()); | |||
} | |||
} | |||
/** | |||
* Check if a username exists on the LDAP server. | |||
* @global type $ldap_config | |||
* @param type $username | |||
* @return boolean true if yes, else false | |||
*/ | |||
function user_exists_ldap($username, $password) { | |||
global $ldap_config; | |||
try { | |||
$ldap = new LdapManager($ldap_config); | |||
$username = strtolower($username); | |||
if (!$ldap->authenticate($username, $password, $message, $code)) { | |||
switch ($code) { | |||
case ADResponseCodes::ACCOUNT_INVALID: | |||
return false; | |||
case ADResponseCodes::ACCOUNT_CREDENTIALS_INVALID: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_RESTRICTIONS: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_RESTRICTIONS_TIME: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_RESTRICTIONS_DEVICE: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_PASSWORD_EXPIRED: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_DISABLED: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_CONTEXT_IDS: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_EXPIRED: | |||
return false; | |||
case ADResponseCodes::ACCOUNT_PASSWORD_MUST_CHANGE: | |||
return true; | |||
case ADResponseCodes::ACCOUNT_LOCKED: | |||
return true; | |||
default: | |||
return false; | |||
} | |||
} | |||
return true; | |||
} catch (Exception $e) { | |||
sendError("LDAP error: " . $e->getMessage()); | |||
} | |||
} | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// 2-factor authentication // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/** | |||
* Check if a user has TOTP setup | |||
* @global $database $database | |||
@@ -35,6 +320,7 @@ function doLoginUser($username) { | |||
*/ | |||
function userHasTOTP($username) { | |||
global $database; | |||
$username = strtolower($username); | |||
$secret = $database->select('accounts', 'authsecret', ['username' => $username])[0]; | |||
if (is_empty($secret)) { | |||
return false; | |||
@@ -49,10 +335,11 @@ function userHasTOTP($username) { | |||
*/ | |||
function newTOTP($username) { | |||
global $database; | |||
$username = strtolower($username); | |||
$secret = random_bytes(20); | |||
$encoded_secret = Base32::encode($secret); | |||
$userdata = $database->select('accounts', ['email', 'authsecret'], ['username' => $username])[0]; | |||
$totp = new TOTP($userdata['email'], $encoded_secret); | |||
$userdata = $database->select('accounts', ['email', 'authsecret', 'realname'], ['username' => $username])[0]; | |||
$totp = new TOTP((is_null($userdata['email']) ? $userdata['realname'] : $userdata['email']), $encoded_secret); | |||
$totp->setIssuer(SYSTEM_NAME); | |||
return $totp->getProvisioningUri(); | |||
} | |||
@@ -65,6 +352,7 @@ function newTOTP($username) { | |||
*/ | |||
function saveTOTP($username, $secret) { | |||
global $database; | |||
$username = strtolower($username); | |||
$database->update('accounts', ['authsecret' => $secret], ['username' => $username]); | |||
} | |||
@@ -77,6 +365,7 @@ function saveTOTP($username, $secret) { | |||
*/ | |||
function verifyTOTP($username, $code) { | |||
global $database; | |||
$username = strtolower($username); | |||
$userdata = $database->select('accounts', ['email', 'authsecret'], ['username' => $username])[0]; | |||
if (is_empty($userdata['authsecret'])) { | |||
return false; |
@@ -3,7 +3,7 @@ | |||
<type>org.netbeans.modules.php.project</type> | |||
<configuration> | |||
<data xmlns="http://www.netbeans.org/ns/php-project/1"> | |||
<name>NetsymsBusinessSSO</name> | |||
<name>BusinessPortal</name> | |||
</data> | |||
</configuration> | |||
</project> |
@@ -16,9 +16,10 @@ $session_length = 60 * 60; // 1 hour | |||
session_set_cookie_params($session_length, "/", null, false, true); | |||
session_start(); // stick some cookies in it | |||
// | |||
// Composer | |||
require __DIR__ . '/vendor/autoload.php'; | |||
// Settings file | |||
require __DIR__ . '/settings.php'; | |||
// List of alert messages | |||
@@ -123,27 +124,6 @@ function lang2($key, $replace, $echo = true) { | |||
} | |||
} | |||
/** | |||
* Add a user to the system. /!\ Assumes input is OK /!\ | |||
* @param string $username Username, saved in lowercase. | |||
* @param string $password Password, will be hashed before saving. | |||
* @param string $realname User's real legal name | |||
* @param string $email User's email address. | |||
* @return int The new user's ID number in the database. | |||
*/ | |||
function adduser($username, $password, $realname, $email = "NOEMAIL@EXAMPLE.COM", $phone1 = "", $phone2 = "") { | |||
global $database; | |||
$database->insert('accounts', [ | |||
'username' => strtolower($username), | |||
'password' => encryptPassword($password), | |||
'realname' => $realname, | |||
'email' => $email, | |||
'phone1' => $phone1, | |||
'phone2' => $phone2 | |||
]); | |||
return $database->id(); | |||
} | |||
/** | |||
* Checks if an email address is valid. | |||
* @param string $email Email to check | |||
@@ -153,87 +133,6 @@ function isValidEmail($email) { | |||
return filter_var($email, FILTER_VALIDATE_EMAIL); | |||
} | |||
/** | |||
* Check if an email exists in the database. | |||
* @param String $email | |||
*/ | |||
function email_exists($email) { | |||
global $database; | |||
return $database->has('accounts', ['email' => $email, "LIMIT" => QUERY_LIMIT]); | |||
} | |||
/** | |||
* Check if a username exists in the database. | |||
* @param String $username | |||
*/ | |||
function user_exists($username) { | |||
global $database; | |||
return $database->has('accounts', ['username' => $username, "LIMIT" => QUERY_LIMIT]); | |||
} | |||
/** | |||
* Checks the given credentials against the database. | |||
* @param string $username | |||
* @param string $password | |||
* @return boolean True if OK, else false | |||
*/ | |||
function authenticate_user($username, $password) { | |||
global $database; | |||
if (is_empty($username) || is_empty($password)) { | |||
return false; | |||
} | |||
if (!user_exists($username)) { | |||
return false; | |||
} | |||
$hash = $database->select('accounts', ['password'], ['username' => $username, "LIMIT" => 1])[0]['password']; | |||
return (comparePassword($password, $hash)); | |||
} | |||
function get_account_status($username) { | |||
global $database; | |||
$statuscode = $database->select('accounts', [ | |||
'[>]acctstatus' => [ | |||
'acctstatus' => 'statusid' | |||
] | |||
], [ | |||
'accounts.acctstatus', | |||
'acctstatus.statuscode' | |||
], [ | |||
'username' => $username, | |||
"LIMIT" => 1 | |||
] | |||
)[0]['statuscode']; | |||
return $statuscode; | |||
} | |||
/** | |||
* Checks the given credentials to see if they're legit. | |||
* @param string $username | |||
* @param string $password | |||
* @return boolean True if OK, else false | |||
*/ | |||
function authenticate_user_ldap($username, $password) { | |||
$ds = ldap_connect(LDAP_SERVER); | |||
if ($ds) { | |||
$sr = ldap_search($ds, LDAP_BASEDN, "(|(uid=" . $username . ")(mail=" . $username . "))", ['cn', 'uid', 'mail']); | |||
if (ldap_count_entries($ds, $sr) == 1) { | |||
$info = ldap_get_entries($ds, $sr); | |||
$name = $info[0]["cn"][0]; | |||
$uid = $info[0]["uid"][0]; | |||
$mail = $info[0]["mail"][0]; | |||
$_SESSION['uid'] = $uid; | |||
$_SESSION['name'] = $name; | |||
$_SESSION['mail'] = $mail; | |||
return true; | |||
} else if (ldap_count_entries($ds, $sr) > 1) { | |||
sendError("Multiple users matched search criteria. Unsure which one you are."); | |||
} else { | |||
return false; | |||
} | |||
} else { | |||
sendError("Login server offline."); | |||
} | |||
} | |||
/** | |||
* Hashes the given plaintext password |
@@ -13,8 +13,28 @@ define("DB_USER", "sso"); | |||
define("DB_PASS", ""); | |||
define("DB_CHARSET", "utf8"); | |||
define("LDAP_SERVER", "example.com"); | |||
define("LDAP_BASEDN", "ou=users,dc=example,dc=com"); | |||
define("LDAP_ENABLED", TRUE); | |||
// See https://github.com/ldaptools/ldaptools/blob/master/docs/en/reference/Main-Configuration.md | |||
// for info on the LDAP config | |||
/* | |||
* Begin LDAP Configuration | |||
*/ | |||
use LdapTools\Configuration; | |||
use LdapTools\DomainConfiguration; | |||
$ldap_config = new Configuration(); | |||
$ldap_config_domain = (new DomainConfiguration('example')) | |||
->setDomainName("example.com") | |||
->setServers(['192.168.25.131']) | |||
->setLazyBind(TRUE) | |||
->setUsername("readonly-bind") | |||
->setPassword("password") | |||
->setUseTls(TRUE); | |||
$ldap_config->addDomain($ldap_config_domain); | |||
/* | |||
* End LDAP Configuration | |||
*/ | |||
define("SITE_TITLE", "Netsyms Business Apps :: Single Sign On"); | |||
@@ -27,6 +47,12 @@ define("TIMEZONE", "America/Denver"); | |||
// Base URL for site links. | |||
define('URL', 'http://localhost:8000/'); | |||
// Use reCAPTCHA on login screen | |||
// https://www.google.com/recaptcha/ | |||
define("RECAPTCHA_ENABLED", FALSE); | |||
define('RECAPTCHA_SITE_KEY', ''); | |||
define('RECAPTCHA_SECRET_KEY', ''); | |||
// See lang folder for language options | |||
define('LANGUAGE', "en_us"); | |||
@@ -46,9 +72,10 @@ define("QUERY_LIMIT", 1000); | |||
/////////////////////////////////////////////////////////////////////////////////////////////// | |||
// /!\ Warning: Changing these values may violate the terms of your license agreement! /!\ // | |||
/////////////////////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////// | |||
// /!\ Warning: Changing these values may /!\ // | |||
// /!\ violate the terms of your license agreement! /!\ // | |||
////////////////////////////////////////////////////////////// | |||
define("LICENSE_TEXT", "<b>Unlicensed Demo: For Trial Use Only</b>"); | |||
define("COPYRIGHT_NAME", "Netsyms Technologies"); | |||
///////////////////////////////////////////////////////////////////////////////////////////// | |||
////////////////////////////////////////////////////////////// |
@@ -0,0 +1,78 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<!-- Created with Inkscape (http://www.inkscape.org/) --> | |||
<svg | |||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||
xmlns:cc="http://creativecommons.org/ns#" | |||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||
xmlns:svg="http://www.w3.org/2000/svg" | |||
xmlns="http://www.w3.org/2000/svg" | |||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||
width="512" | |||
height="512" | |||
viewBox="0 0 512.00001 512.00001" | |||
id="svg2" | |||
version="1.1" | |||
inkscape:version="0.91 r13725" | |||
sodipodi:docname="logo.svg" | |||
inkscape:export-filename="/home/skylar/Documents/Projects/Assets/BusinessPortal/logo_512.png" | |||
inkscape:export-xdpi="90" | |||
inkscape:export-ydpi="90"> | |||
<defs | |||
id="defs4" /> | |||
<sodipodi:namedview | |||
id="base" | |||
pagecolor="#ffffff" | |||
bordercolor="#666666" | |||
borderopacity="1.0" | |||
inkscape:pageopacity="0.0" | |||
inkscape:pageshadow="2" | |||
inkscape:zoom="0.49497475" | |||
inkscape:cx="-135.9681" | |||
inkscape:cy="352.66131" | |||
inkscape:document-units="px" | |||
inkscape:current-layer="layer1" | |||
showgrid="false" | |||
units="px" /> | |||
<metadata | |||
id="metadata7"> | |||
<rdf:RDF> | |||
<cc:Work | |||
rdf:about=""> | |||
<dc:format>image/svg+xml</dc:format> | |||
<dc:type | |||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||
<dc:title /> | |||
</cc:Work> | |||
</rdf:RDF> | |||
</metadata> | |||
<g | |||
inkscape:label="Layer 1" | |||
inkscape:groupmode="layer" | |||
id="layer1" | |||
transform="translate(0,-540.36216)"> | |||
<rect | |||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:20;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.74509804" | |||
id="rect4726" | |||
width="512" | |||
height="512" | |||
x="0" | |||
y="540.36218" | |||
rx="50" | |||
ry="50" /> | |||
<ellipse | |||
style="opacity:1;fill:none;fill-opacity:1;stroke:#2196f3;stroke-width:50;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | |||
id="path4155" | |||
cx="901.47205" | |||
cy="-256" | |||
rx="68.690376" | |||
ry="193.9493" | |||
transform="matrix(0,1,-1,0,0,0)" /> | |||
<path | |||
inkscape:connector-curvature="0" | |||
d="m 257.45991,599.83707 c 9.94158,-3.2506 20.98401,-3.01096 30.77413,0.67362 8.13772,3.03356 15.37803,8.41343 20.65625,15.31019 5.7326,7.42341 9.11199,16.6258 9.55504,25.99551 0.63974,11.77034 -3.4201,23.71233 -11.14414,32.62095 6.11458,6.07391 10.75535,13.62837 13.37297,21.84299 3.28899,10.26035 3.40883,21.51078 0.35265,31.84111 -2.44585,8.32302 -6.96227,16.01318 -12.98644,22.24763 -5.15388,5.31434 -11.38153,9.60704 -18.23981,12.40548 -0.0129,14.28395 -0.007,28.56791 -0.004,42.85187 -0.50863,0 -1.01271,-0.0143 -1.51227,-0.0143 0.0129,30.01462 -10e-4,60.02924 0.009,90.04386 0.0543,0.47919 -0.14918,0.95395 -0.54929,1.23189 -4.56391,3.42459 -9.12781,6.85389 -13.69623,10.2762 -0.5787,0.4362 -1.43991,0.42506 -2.02089,0.0143 -5.08607,-3.42245 -10.18796,-6.8199 -15.26953,-10.24677 -0.44305,-0.26224 -0.65099,-0.76871 -0.58547,-1.26589 0.0159,-30.01462 -0.0129,-60.02696 0.0159,-90.04172 -2.60182,0 -5.20363,0 -7.80317,0 -0.0114,-4.06875 0.0339,-8.13992 -0.0181,-12.20652 -0.53574,1.44442 -1.03529,2.90698 -1.60493,4.3424 -0.43399,-0.18082 -0.86577,-0.34593 -1.29978,-0.50632 -9.53697,26.00443 -19.14397,51.98187 -28.70129,77.97974 -0.13112,0.4272 -0.38428,0.85668 -0.859,0.94937 -5.01825,1.51913 -10.04102,3.01768 -15.06381,4.52094 -0.74369,0.26452 -1.57784,-0.1014 -1.97343,-0.75727 -3.15789,-4.37183 -6.3248,-8.7368 -9.50077,-13.09491 -0.37071,-0.47476 -0.80472,-1.06922 -0.486,-1.6908 7.00975,-19.06727 14.04209,-38.12755 21.05862,-57.19253 2.5566,-6.99387 5.19005,-13.96288 7.69466,-20.97717 -2.25143,-0.78213 -4.48025,-1.62982 -6.71587,-2.45493 4.56389,-12.36478 9.10972,-24.73398 13.66911,-37.10119 -6.0965,-5.61043 -10.75082,-12.76712 -13.42272,-20.60638 -3.3568,-9.71789 -3.59191,-20.48227 -0.62388,-30.32899 3.38618,-11.61193 11.17807,-21.8587 21.46999,-28.21756 -5.26461,-8.55355 -7.54771,-18.87946 -6.50336,-28.85942 0.91548,-9.41942 4.851,-18.50206 11.03791,-25.65645 5.5314,-6.43108 12.84403,-11.32052 20.91847,-13.92679 m -13.13113,14.70443 c -6.2276,5.76422 -10.57903,13.53348 -12.16813,21.8746 -1.94174,9.85347 -0.052,20.40536 5.25335,28.94094 4.48253,-2.07972 9.27248,-3.49243 14.16418,-4.18643 0.74819,-0.10855 1.51225,-0.12855 2.24914,-0.3278 7.64496,-2.25365 15.79171,-2.74188 23.66271,-1.53254 9.18205,1.406 17.95044,5.28493 25.23598,11.04019 2.56112,-3.05396 4.71761,-6.46055 6.29543,-10.12481 4.19092,-9.57528 4.426,-20.79176 0.65329,-30.53671 -2.92507,-7.68337 -8.28467,-14.40606 -15.09097,-19.01291 -7.28325,-4.97078 -16.23022,-7.42788 -25.03026,-6.89669 -9.32448,0.49954 -18.40936,4.3808 -25.22472,10.76216 m 20.4596,59.08886 c -3.87446,1.01265 -7.05947,4.14802 -8.22589,7.9681 7.28328,2.99525 15.45491,3.74567 23.17444,2.22669 -0.36167,-3.1128 -1.94175,-6.08077 -4.4102,-8.02923 -2.90697,-2.33281 -6.94871,-3.20306 -10.53835,-2.16556 m -7.45051,14.82199 c 1.12344,2.37566 2.91375,4.45081 5.19004,5.78911 3.65069,2.2017 8.43386,2.41865 12.2337,0.46562 1.66825,-1.08506 2.90924,-2.7103 3.84961,-4.44181 -7.10695,1.04193 -14.43996,0.39321 -21.27335,-1.81292 z" | |||
id="path3" | |||
style="fill:#ff9100;fill-opacity:1" /> | |||
</g> | |||
</svg> |