@@ -0,0 +1,4 @@ | |||
vendor | |||
settings.php | |||
nbproject/private | |||
database_model.mwb.bak |
@@ -0,0 +1,62 @@ | |||
<?php | |||
/** | |||
* 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 = "") { | |||
global $VARS; | |||
if ($arg == "") { | |||
header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=" . $msg); | |||
} else { | |||
header("Location: app.php?page=" . urlencode($VARS['source']) . "&msg=$msg&arg=$arg"); | |||
} | |||
die(); | |||
} | |||
switch ($VARS['action']) { | |||
case "signout": | |||
session_destroy(); | |||
header('Location: index.php'); | |||
die("Logged out."); | |||
case "chpasswd": | |||
if ($_SESSION['password'] == $VARS['oldpass']) { | |||
if ($VARS['newpass'] == $VARS['conpass']) { | |||
$passrank = checkWorst500List($VARS['newpass']); | |||
if ($passrank !== FALSE) { | |||
returnToSender("password_500", $passrank); | |||
} | |||
if (strlen($VARS['newpass']) < MIN_PASSWORD_LENGTH) { | |||
returnToSender("weak_password"); | |||
} | |||
$database->update('accounts', ['password' => encryptPassword($VARS['newpass'])], ['uid' => $_SESSION['uid']]); | |||
$_SESSION['password'] = $VARS['newpass']; | |||
returnToSender("password_updated"); | |||
} else { | |||
returnToSender("new_password_mismatch"); | |||
} | |||
} else { | |||
returnToSender("old_password_mismatch"); | |||
} | |||
break; | |||
case "add2fa": | |||
if (is_empty($VARS['secret'])) { | |||
returnToSender("invalid_parameters"); | |||
} | |||
$database->update('accounts', ['authsecret' => $VARS['secret']], ['uid' => $_SESSION['uid']]); | |||
returnToSender("2fa_enabled"); | |||
case "rm2fa": | |||
$database->update('accounts', ['authsecret' => ""], ['uid' => $_SESSION['uid']]); | |||
returnToSender("2fa_removed"); | |||
break; | |||
} |
@@ -0,0 +1,128 @@ | |||
<?php | |||
require_once __DIR__ . "/required.php"; | |||
if ($_SESSION['loggedin'] != true) { | |||
header('Location: index.php'); | |||
die("Session expired. Log in again to continue."); | |||
} | |||
require_once __DIR__ . "/pages.php"; | |||
$pageid = "home"; | |||
if (!is_empty($_GET['page'])) { | |||
$pg = strtolower($_GET['page']); | |||
$pg = preg_replace('/[^0-9a-z_]/', "", $pg); | |||
if (array_key_exists($pg, PAGES) && file_exists(__DIR__ . "/pages/" . $pg . ".php")) { | |||
$pageid = $pg; | |||
} else { | |||
$pageid = "404"; | |||
} | |||
} | |||
?> | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
<meta name="viewport" contgreent="width=device-width, initial-scale=1"> | |||
<title><?php echo SITE_TITLE; ?></title> | |||
<link href="static/css/bootstrap.min.css" rel="stylesheet"> | |||
<link href="static/css/font-awesome.min.css" rel="stylesheet"> | |||
<link href="static/css/app.css" rel="stylesheet"> | |||
</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"> | |||
<img class="img-responsive banner-image" src="static/img/banner.png" /> | |||
</div> | |||
</div> | |||
<nav class="navbar navbar-inverse"> | |||
<div class="container-fluid"> | |||
<div class="navbar-header"> | |||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse"> | |||
<span class="sr-only">Toggle navigation</span> | |||
<span class="icon-bar"></span> | |||
<span class="icon-bar"></span> | |||
<span class="icon-bar"></span> | |||
</button> | |||
<a class="navbar-brand" href="app.php?page=home"> | |||
<?php | |||
// add breadcrumb-y thing | |||
//lang("home"); | |||
//echo " <i class=\"fa fa-caret-right\"></i> "; | |||
lang(PAGES[$pageid]['title']); | |||
?> | |||
</a> | |||
</div> | |||
<div class="collapse navbar-collapse" id="navbar-collapse"> | |||
<ul class="nav navbar-nav"> | |||
</ul> | |||
<ul class="nav navbar-nav navbar-right"> | |||
<li class="dropdown"> | |||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-gears fa-fw"></i> <?php lang("options") ?> <span class="caret"></span></a> | |||
<ul class="dropdown-menu" role="menu"> | |||
<li><a href="app.php?page=security"><i class="fa fa-lock fa-fw"></i> <?php lang("account security") ?></a></li> | |||
<li class="divider"></li> | |||
<li><a href="action.php?action=signout"><i class="fa fa-sign-out fa-fw"></i> <?php lang("sign out") ?></a></li> | |||
</ul> | |||
</li> | |||
</ul> | |||
</div> | |||
</div> | |||
</nav> | |||
<?php | |||
// Alert messages | |||
if (!is_empty($_GET['msg']) && array_key_exists($_GET['msg'], MESSAGES)) { | |||
// optional string generation argument | |||
if (is_empty($_GET['arg'])) { | |||
$alertmsg = lang(MESSAGES[$_GET['msg']]['string'], false); | |||
} else { | |||
$alertmsg = lang2(MESSAGES[$_GET['msg']]['string'], ["arg" => $_GET['arg']], false); | |||
} | |||
$alerttype = MESSAGES[$_GET['msg']]['type']; | |||
$alerticon = "square-o"; | |||
switch (MESSAGES[$_GET['msg']]['type']) { | |||
case "danger": | |||
$alerticon = "times"; | |||
break; | |||
case "warning": | |||
$alerticon = "exclamation-triangle"; | |||
break; | |||
case "info": | |||
$alerticon = "info-circle"; | |||
break; | |||
case "success": | |||
$alerticon = "check"; | |||
break; | |||
} | |||
echo <<<END | |||
<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 class="alert alert-dismissible alert-$alerttype"> | |||
<button type="button" class="close">×</button> | |||
<i class="fa fa-$alerticon"></i> $alertmsg | |||
</div> | |||
</div> | |||
</div> | |||
END; | |||
} | |||
?> | |||
<div> | |||
<?php | |||
include_once __DIR__ . '/pages/' . $pageid . ".php"; | |||
?> | |||
</div> | |||
<div class="footer"> | |||
<?php echo LICENSE_TEXT; ?><br /> | |||
Copyright © <?php echo date('Y'); ?> <?php echo COPYRIGHT_NAME; ?> | |||
</div> | |||
</div> | |||
<script src="static/js/jquery-3.2.1.min.js"></script> | |||
<script src="static/js/bootstrap.min.js"></script> | |||
<script src="static/js/app.js"></script> | |||
</body> | |||
</html> |
@@ -0,0 +1,16 @@ | |||
{ | |||
"name": "netsyms/web-app-template", | |||
"description": "Simple framework for rapid webapp development", | |||
"type": "project", | |||
"require": { | |||
"catfan/medoo": "^1.2", | |||
"spomky-labs/otphp": "^8.3" | |||
}, | |||
"license": "MIT", | |||
"authors": [ | |||
{ | |||
"name": "Skylar Ittner", | |||
"email": "admin@netsyms.com" | |||
} | |||
] | |||
} |
@@ -0,0 +1,461 @@ | |||
{ | |||
"_readme": [ | |||
"This file locks the dependencies of your project to a known state", | |||
"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": "51c1672b4dea32e60865b4c0cd9ff8e1", | |||
"packages": [ | |||
{ | |||
"name": "beberlei/assert", | |||
"version": "v2.7.4", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/beberlei/assert.git", | |||
"reference": "3ee3bc468a3ce4bbfc3d74f53c6cdb5242d39d1a" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/beberlei/assert/zipball/3ee3bc468a3ce4bbfc3d74f53c6cdb5242d39d1a", | |||
"reference": "3ee3bc468a3ce4bbfc3d74f53c6cdb5242d39d1a", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"ext-mbstring": "*", | |||
"php": ">=5.3" | |||
}, | |||
"require-dev": { | |||
"friendsofphp/php-cs-fixer": "^2.1.1", | |||
"phpunit/phpunit": "^4|^5" | |||
}, | |||
"type": "library", | |||
"autoload": { | |||
"psr-4": { | |||
"Assert\\": "lib/Assert" | |||
}, | |||
"files": [ | |||
"lib/Assert/functions.php" | |||
] | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"BSD-2-Clause" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Benjamin Eberlei", | |||
"email": "kontakt@beberlei.de", | |||
"role": "Lead Developer" | |||
}, | |||
{ | |||
"name": "Richard Quadling", | |||
"email": "rquadling@gmail.com", | |||
"role": "Collaborator" | |||
} | |||
], | |||
"description": "Thin assertion library for input validation in business models.", | |||
"keywords": [ | |||
"assert", | |||
"assertion", | |||
"validation" | |||
], | |||
"time": "2017-03-14T18:06:52+00:00" | |||
}, | |||
{ | |||
"name": "catfan/medoo", | |||
"version": "v1.2.1", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/catfan/Medoo.git", | |||
"reference": "b5a788c90c44db0f978512c890cb6962af4685e8" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/catfan/Medoo/zipball/b5a788c90c44db0f978512c890cb6962af4685e8", | |||
"reference": "b5a788c90c44db0f978512c890cb6962af4685e8", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"ext-pdo": "*", | |||
"php": ">=5.4" | |||
}, | |||
"suggest": { | |||
"ext-pdo_dblib": "For MSSQL or Sybase databases on Linux/UNIX platform", | |||
"ext-pdo_mysql": "For MySQL or MariaDB databases", | |||
"ext-pdo_oci": "For Oracle databases", | |||
"ext-pdo_pqsql": "For PostgreSQL databases", | |||
"ext-pdo_sqlite": "For SQLite databases", | |||
"ext-pdo_sqlsrv": "For MSSQL databases on Windows platform" | |||
}, | |||
"type": "framework", | |||
"autoload": { | |||
"psr-4": { | |||
"Medoo\\": "/src" | |||
} | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Angel Lai", | |||
"email": "angel@catfan.me" | |||
} | |||
], | |||
"description": "The Lightest PHP database framework to accelerate development", | |||
"homepage": "http://medoo.in", | |||
"keywords": [ | |||
"database", | |||
"lightweight", | |||
"mssql", | |||
"mysql", | |||
"php framework", | |||
"sql", | |||
"sqlite" | |||
], | |||
"time": "2017-02-17T16:05:35+00:00" | |||
}, | |||
{ | |||
"name": "christian-riesen/base32", | |||
"version": "1.3.1", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/ChristianRiesen/base32.git", | |||
"reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/ChristianRiesen/base32/zipball/0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa", | |||
"reference": "0a31e50c0fa9b1692d077c86ac188eecdcbaf7fa", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"php": ">=5.3.0" | |||
}, | |||
"require-dev": { | |||
"phpunit/phpunit": "4.*", | |||
"satooshi/php-coveralls": "0.*" | |||
}, | |||
"type": "library", | |||
"extra": { | |||
"branch-alias": { | |||
"dev-master": "1.1.x-dev" | |||
} | |||
}, | |||
"autoload": { | |||
"psr-4": { | |||
"Base32\\": "src/" | |||
} | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Christian Riesen", | |||
"email": "chris.riesen@gmail.com", | |||
"homepage": "http://christianriesen.com", | |||
"role": "Developer" | |||
} | |||
], | |||
"description": "Base32 encoder/decoder according to RFC 4648", | |||
"homepage": "https://github.com/ChristianRiesen/base32", | |||
"keywords": [ | |||
"base32", | |||
"decode", | |||
"encode", | |||
"rfc4648" | |||
], | |||
"time": "2016-05-05T11:49:03+00:00" | |||
}, | |||
{ | |||
"name": "paragonie/random_compat", | |||
"version": "v2.0.10", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/paragonie/random_compat.git", | |||
"reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", | |||
"reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"php": ">=5.2.0" | |||
}, | |||
"require-dev": { | |||
"phpunit/phpunit": "4.*|5.*" | |||
}, | |||
"suggest": { | |||
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." | |||
}, | |||
"type": "library", | |||
"autoload": { | |||
"files": [ | |||
"lib/random.php" | |||
] | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Paragon Initiative Enterprises", | |||
"email": "security@paragonie.com", | |||
"homepage": "https://paragonie.com" | |||
} | |||
], | |||
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", | |||
"keywords": [ | |||
"csprng", | |||
"pseudorandom", | |||
"random" | |||
], | |||
"time": "2017-03-13T16:27:32+00:00" | |||
}, | |||
{ | |||
"name": "spomky-labs/otphp", | |||
"version": "v8.3.0", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/Spomky-Labs/otphp.git", | |||
"reference": "8c90e16ba48fe7c306832611e22c5bad2d663a98" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/Spomky-Labs/otphp/zipball/8c90e16ba48fe7c306832611e22c5bad2d663a98", | |||
"reference": "8c90e16ba48fe7c306832611e22c5bad2d663a98", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"beberlei/assert": "^2.4", | |||
"christian-riesen/base32": "^1.1", | |||
"paragonie/random_compat": "^2.0", | |||
"php": "^5.5|^7.0", | |||
"symfony/polyfill-mbstring": "^1.1", | |||
"symfony/polyfill-php56": "^1.1" | |||
}, | |||
"require-dev": { | |||
"phpunit/phpunit": "~4.0|^5.0", | |||
"satooshi/php-coveralls": "^1.0" | |||
}, | |||
"type": "library", | |||
"extra": { | |||
"branch-alias": { | |||
"dev-master": "8.2.x-dev" | |||
} | |||
}, | |||
"autoload": { | |||
"psr-4": { | |||
"OTPHP\\": "src/" | |||
} | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Florent Morselli", | |||
"homepage": "https://github.com/Spomky" | |||
}, | |||
{ | |||
"name": "All contributors", | |||
"homepage": "https://github.com/Spomky-Labs/otphp/contributors" | |||
} | |||
], | |||
"description": "A PHP library for generating one time passwords according to RFC 4226 (HOTP Algorithm) and the RFC 6238 (TOTP Algorithm) and compatible with Google Authenticator", | |||
"homepage": "https://github.com/Spomky-Labs/otphp", | |||
"keywords": [ | |||
"FreeOTP", | |||
"RFC 4226", | |||
"RFC 6238", | |||
"google authenticator", | |||
"hotp", | |||
"otp", | |||
"totp" | |||
], | |||
"time": "2016-12-08T10:46:02+00:00" | |||
}, | |||
{ | |||
"name": "symfony/polyfill-mbstring", | |||
"version": "v1.3.0", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/symfony/polyfill-mbstring.git", | |||
"reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", | |||
"reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"php": ">=5.3.3" | |||
}, | |||
"suggest": { | |||
"ext-mbstring": "For best performance" | |||
}, | |||
"type": "library", | |||
"extra": { | |||
"branch-alias": { | |||
"dev-master": "1.3-dev" | |||
} | |||
}, | |||
"autoload": { | |||
"psr-4": { | |||
"Symfony\\Polyfill\\Mbstring\\": "" | |||
}, | |||
"files": [ | |||
"bootstrap.php" | |||
] | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Nicolas Grekas", | |||
"email": "p@tchwork.com" | |||
}, | |||
{ | |||
"name": "Symfony Community", | |||
"homepage": "https://symfony.com/contributors" | |||
} | |||
], | |||
"description": "Symfony polyfill for the Mbstring extension", | |||
"homepage": "https://symfony.com", | |||
"keywords": [ | |||
"compatibility", | |||
"mbstring", | |||
"polyfill", | |||
"portable", | |||
"shim" | |||
], | |||
"time": "2016-11-14T01:06:16+00:00" | |||
}, | |||
{ | |||
"name": "symfony/polyfill-php56", | |||
"version": "v1.3.0", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/symfony/polyfill-php56.git", | |||
"reference": "1dd42b9b89556f18092f3d1ada22cb05ac85383c" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/1dd42b9b89556f18092f3d1ada22cb05ac85383c", | |||
"reference": "1dd42b9b89556f18092f3d1ada22cb05ac85383c", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"php": ">=5.3.3", | |||
"symfony/polyfill-util": "~1.0" | |||
}, | |||
"type": "library", | |||
"extra": { | |||
"branch-alias": { | |||
"dev-master": "1.3-dev" | |||
} | |||
}, | |||
"autoload": { | |||
"psr-4": { | |||
"Symfony\\Polyfill\\Php56\\": "" | |||
}, | |||
"files": [ | |||
"bootstrap.php" | |||
] | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Nicolas Grekas", | |||
"email": "p@tchwork.com" | |||
}, | |||
{ | |||
"name": "Symfony Community", | |||
"homepage": "https://symfony.com/contributors" | |||
} | |||
], | |||
"description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", | |||
"homepage": "https://symfony.com", | |||
"keywords": [ | |||
"compatibility", | |||
"polyfill", | |||
"portable", | |||
"shim" | |||
], | |||
"time": "2016-11-14T01:06:16+00:00" | |||
}, | |||
{ | |||
"name": "symfony/polyfill-util", | |||
"version": "v1.3.0", | |||
"source": { | |||
"type": "git", | |||
"url": "https://github.com/symfony/polyfill-util.git", | |||
"reference": "746bce0fca664ac0a575e465f65c6643faddf7fb" | |||
}, | |||
"dist": { | |||
"type": "zip", | |||
"url": "https://api.github.com/repos/symfony/polyfill-util/zipball/746bce0fca664ac0a575e465f65c6643faddf7fb", | |||
"reference": "746bce0fca664ac0a575e465f65c6643faddf7fb", | |||
"shasum": "" | |||
}, | |||
"require": { | |||
"php": ">=5.3.3" | |||
}, | |||
"type": "library", | |||
"extra": { | |||
"branch-alias": { | |||
"dev-master": "1.3-dev" | |||
} | |||
}, | |||
"autoload": { | |||
"psr-4": { | |||
"Symfony\\Polyfill\\Util\\": "" | |||
} | |||
}, | |||
"notification-url": "https://packagist.org/downloads/", | |||
"license": [ | |||
"MIT" | |||
], | |||
"authors": [ | |||
{ | |||
"name": "Nicolas Grekas", | |||
"email": "p@tchwork.com" | |||
}, | |||
{ | |||
"name": "Symfony Community", | |||
"homepage": "https://symfony.com/contributors" | |||
} | |||
], | |||
"description": "Symfony utilities for portability of PHP codes", | |||
"homepage": "https://symfony.com", | |||
"keywords": [ | |||
"compat", | |||
"compatibility", | |||
"polyfill", | |||
"shim" | |||
], | |||
"time": "2016-11-14T01:06:16+00:00" | |||
} | |||
], | |||
"packages-dev": [], | |||
"aliases": [], | |||
"minimum-stability": "stable", | |||
"stability-flags": [], | |||
"prefer-stable": false, | |||
"prefer-lowest": false, | |||
"platform": [], | |||
"platform-dev": [] | |||
} |
@@ -0,0 +1,117 @@ | |||
<?php | |||
require_once __DIR__ . "/required.php"; | |||
require_once __DIR__ . "/lib/login.php"; | |||
/* Authenticate user */ | |||
$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": | |||
sendLoginAlertEmail($VARS['username']); | |||
$userpass_ok = true; | |||
break; | |||
} | |||
if ($userpass_ok) { | |||
if (userHasTOTP($VARS['username'])) { | |||
$multiauth = true; | |||
} else { | |||
doLoginUser($VARS['username'], $VARS['password']); | |||
header('Location: app.php'); | |||
die("Logged in, go to app.php"); | |||
} | |||
} | |||
} else { | |||
$alert = lang("login incorrect", false); | |||
} | |||
} else if ($VARS['progress'] == "2") { | |||
if (verifyTOTP($VARS['username'], $VARS['authcode'])) { | |||
doLoginUser($VARS['username'], $VARS['password']); | |||
header('Location: app.php'); | |||
die("Logged in, go to app.php"); | |||
} else { | |||
$alert = lang("2fa incorrect", false); | |||
} | |||
} | |||
?> | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
<meta name="viewport" contgreent="width=device-width, initial-scale=1"> | |||
<title><?php echo SITE_TITLE; ?></title> | |||
<link href="static/css/bootstrap.min.css" rel="stylesheet"> | |||
<link href="static/css/app.css" rel="stylesheet"> | |||
</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" /> | |||
</div> | |||
<div class="panel panel-primary"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"><?php lang("sign in"); ?></h3> | |||
</div> | |||
<div class="panel-body"> | |||
<form action="" method="POST"> | |||
<?php | |||
if (!is_empty($alert)) { | |||
?> | |||
<div class="alert alert-danger"> | |||
<?php echo $alert; ?> | |||
</div> | |||
<?php | |||
} | |||
if ($multiauth != true) { | |||
?> | |||
<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 /> | |||
<input type="hidden" name="progress" value="1" /> | |||
<?php | |||
} else if ($multiauth) { | |||
?> | |||
<div class="alert alert-info"> | |||
<?php lang("2fa prompt"); ?> | |||
</div> | |||
<input type="text" class="form-control" name="authcode" placeholder="<?php lang("authcode"); ?>" required="required" autofocus /><br /> | |||
<input type="hidden" name="progress" value="2" /> | |||
<input type="hidden" name="username" value="<?php echo $VARS['username']; ?>" /> | |||
<?php | |||
} | |||
?> | |||
<button type="submit" class="btn btn-primary"> | |||
<?php lang("continue"); ?> | |||
</button> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="footer"> | |||
<?php echo LICENSE_TEXT; ?><br /> | |||
Copyright © <?php echo date('Y'); ?> <?php echo COPYRIGHT_NAME; ?> | |||
</div> | |||
</div> | |||
<script src="static/js/jquery-3.2.1.min.js"></script> | |||
<script src="static/js/bootstrap.min.js"></script> | |||
</body> | |||
</html> |
@@ -0,0 +1,42 @@ | |||
<?php | |||
define("STRINGS", [ | |||
"sign in" => "Sign In", | |||
"username" => "Username", | |||
"password" => "Password", | |||
"continue" => "Continue", | |||
"authcode" => "Authentication code", | |||
"2fa prompt" => "Enter the six-digit code from your mobile authenticator app.", | |||
"2fa incorrect" => "Authentication code incorrect.", | |||
"login incorrect" => "Login incorrect.", | |||
"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", | |||
"security options" => "Security options", | |||
"account security" => "Account security", | |||
"sign out" => "Sign out", | |||
"settings" => "Settings", | |||
"options" => "Options", | |||
"404 error" => "404 Error", | |||
"page not found" => "Page not found.", | |||
"current password incorrect" => "The current password is incorrect. Try again.", | |||
"new password mismatch" => "The new passwords did not match. Try again.", | |||
"weak password" => "Password does not meet requirements.", | |||
"password updated" => "Password updated successfully.", | |||
"setup 2fa" => "Setup 2-factor authentication", | |||
"2fa removed" => "2-factor authentication disabled.", | |||
"2fa enabled" => "2-factor authentication activated.", | |||
"remove 2fa" => "Disable 2-factor authentication", | |||
"2fa explained" => "2-factor authentication adds more security to your account. You'll need an app such as Google Authenticator on your smartphone. When you have the app installed, you can enable 2-factor authentication by clicking the button below and scanning a QR code with the app. Whenever you sign in in the future, you'll need to input a six-digit code from your phone into the login page when prompted. You can disable 2-factor authentication from this page if you change your mind.", | |||
"2fa active" => "2-factor authentication is active on your account. To remove 2fa, reset your authentication secret, or change to a new security device, click the button below.", | |||
"enable 2fa" => "Enable 2-factor authentication", | |||
"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}", | |||
"home" => "Home", | |||
]); |
@@ -0,0 +1,44 @@ | |||
<?php | |||
define("MESSAGES", [ | |||
"old_password_mismatch" => [ | |||
"string" => "current password incorrect", | |||
"type" => "danger" | |||
], | |||
"new_password_mismatch" => [ | |||
"string" => "new password mismatch", | |||
"type" => "danger" | |||
], | |||
"weak_password" => [ | |||
"string" => "weak password", | |||
"type" => "danger" | |||
], | |||
"password_updated" => [ | |||
"string" => "password updated", | |||
"type" => "success" | |||
], | |||
"2fa_removed" => [ | |||
"string" => "2fa removed", | |||
"type" => "success" | |||
], | |||
"2fa_enabled" => [ | |||
"string" => "2fa enabled", | |||
"type" => "success" | |||
], | |||
"invalid_parameters" => [ | |||
"string" => "invalid parameters", | |||
"type" => "danger" | |||
], | |||
"password_500" => [ | |||
"string" => "password on 500 list", | |||
"type" => "danger" | |||
], | |||
"account_state_error" => [ | |||
"string" => "account state error", | |||
"type" => "danger" | |||
], | |||
"404_error" => [ | |||
"string" => "page not found", | |||
"type" => "info" | |||
] | |||
]); |
@@ -0,0 +1,302 @@ | |||
<?php | |||
/** | |||
* Authentication and account functions | |||
*/ | |||
use Base32\Base32; | |||
use OTPHP\TOTP; | |||
use LdapTools\LdapManager; | |||
use LdapTools\Connection\ADResponseCodes; | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// Account handling // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/** | |||
* 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 = null, $phone1 = "", $phone2 = "") { | |||
global $database; | |||
$database->debug()->insert('accounts', [ | |||
'username' => strtolower($username), | |||
'password' => (is_null($password) ? null : encryptPassword($password)), | |||
'realname' => $realname, | |||
'email' => $email, | |||
'phone1' => $phone1, | |||
'phone2' => $phone2, | |||
'acctstatus' => 1 | |||
]); | |||
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; | |||
$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; | |||
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); | |||
} else if ($loc == "LDAP_ONLY") { | |||
if (authenticate_user_ldap($username, $password) === TRUE) { | |||
try { | |||
$user = (new LdapManager($ldap_config))->getRepository('user')->findOneByUsername($username); | |||
var_dump($user); | |||
adduser($user->getUsername(), null, $user->getName(), ($user->hasEmailAddress() ? $user->getEmailAddress() : null)); | |||
return true; | |||
} catch (Exception $e) { | |||
sendError("LDAP error: " . $e->getMessage()); | |||
} | |||
} else { | |||
return false; | |||
} | |||
} else { | |||
return false; | |||
} | |||
} | |||
/** | |||
* Check if a username exists in the local database. | |||
* @param String $username | |||
*/ | |||
function user_exists($username) { | |||
global $database; | |||
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; | |||
$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, $password) { | |||
global $database; | |||
$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 | |||
} | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// 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; | |||
} | |||
$ldapManager = new LdapManager($ldap_config); | |||
$msg = ""; | |||
$code = 0; | |||
if ($ldapManager->authenticate($username, $password, $msg, $code)) { | |||
return true; | |||
} else { | |||
return $code; | |||
} | |||
} | |||
/** | |||
* 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; | |||
$ldap = new LdapManager($ldap_config); | |||
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; | |||
} | |||
//////////////////////////////////////////////////////////////////////////////// | |||
// 2-factor authentication // | |||
//////////////////////////////////////////////////////////////////////////////// | |||
/** | |||
* Check if a user has TOTP setup | |||
* @global $database $database | |||
* @param string $username | |||
* @return boolean true if TOTP secret exists, else false | |||
*/ | |||
function userHasTOTP($username) { | |||
global $database; | |||
$secret = $database->select('accounts', 'authsecret', ['username' => $username])[0]; | |||
if (is_empty($secret)) { | |||
return false; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Generate a TOTP secret for the given user. | |||
* @param string $username | |||
* @return string OTP provisioning URI (for generating a QR code) | |||
*/ | |||
function newTOTP($username) { | |||
global $database; | |||
$secret = random_bytes(20); | |||
$encoded_secret = Base32::encode($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(); | |||
} | |||
/** | |||
* Save a TOTP secret for the user. | |||
* @global $database $database | |||
* @param string $username | |||
* @param string $secret | |||
*/ | |||
function saveTOTP($username, $secret) { | |||
global $database; | |||
$database->update('accounts', ['authsecret' => $secret], ['username' => $username]); | |||
} | |||
/** | |||
* Verify a TOTP multiauth code | |||
* @global $database | |||
* @param string $username | |||
* @param int $code | |||
* @return boolean true if it's legit, else false | |||
*/ | |||
function verifyTOTP($username, $code) { | |||
global $database; | |||
$userdata = $database->select('accounts', ['email', 'authsecret'], ['username' => $username])[0]; | |||
if (is_empty($userdata['authsecret'])) { | |||
return false; | |||
} | |||
$totp = new TOTP(null, $userdata['authsecret']); | |||
return $totp->verify($code); | |||
} |
@@ -0,0 +1,522 @@ | |||
<?php | |||
/* | |||
* 500 most common passwords, to be used in stopping idiots from having really bad passwords. | |||
* Source: https://github.com/danielmiessler/SecLists/blob/master/Passwords/500-worst-passwords.txt | |||
*/ | |||
/** | |||
* Checks a given password against the list of the 500 most common passwords. | |||
* @param string $search the password to check | |||
* @return false if not found, the password ranking if found | |||
*/ | |||
function checkWorst500List($search) { | |||
$worst_password_list = [ | |||
"123456", | |||
"password", | |||
"12345678", | |||
"1234", | |||
"pussy", | |||
"12345", | |||
"dragon", | |||
"qwerty", | |||
"696969", | |||
"mustang", | |||
"letmein", | |||
"baseball", | |||
"master", | |||
"michael", | |||
"football", | |||
"shadow", | |||
"monkey", | |||
"abc123", | |||
"pass", | |||
"fuckme", | |||
"6969", | |||
"jordan", | |||
"harley", | |||
"ranger", | |||
"iwantu", | |||
"jennifer", | |||
"hunter", | |||
"fuck", | |||
"2000", | |||
"test", | |||
"batman", | |||
"trustno1", | |||
"thomas", | |||
"tigger", | |||
"robert", | |||
"access", | |||
"love", | |||
"buster", | |||
"1234567", | |||
"soccer", | |||
"hockey", | |||
"killer", | |||
"george", | |||
"sexy", | |||
"andrew", | |||
"charlie", | |||
"superman", | |||
"asshole", | |||
"fuckyou", | |||
"dallas", | |||
"jessica", | |||
"panties", | |||
"pepper", | |||
"1111", | |||
"austin", | |||
"william", | |||
"daniel", | |||
"golfer", | |||
"summer", | |||
"heather", | |||
"hammer", | |||
"yankees", | |||
"joshua", | |||
"maggie", | |||
"biteme", | |||
"enter", | |||
"ashley", | |||
"thunder", | |||
"cowboy", | |||
"silver", | |||
"richard", | |||
"fucker", | |||
"orange", | |||
"merlin", | |||
"michelle", | |||
"corvette", | |||
"bigdog", | |||
"cheese", | |||
"matthew", | |||
"121212", | |||
"patrick", | |||
"martin", | |||
"freedom", | |||
"ginger", | |||
"blowjob", | |||
"nicole", | |||
"sparky", | |||
"yellow", | |||
"camaro", | |||
"secret", | |||
"dick", | |||
"falcon", | |||
"taylor", | |||
"111111", | |||
"131313", | |||
"123123", | |||
"bitch", | |||
"hello", | |||
"scooter", | |||
"please", | |||
"porsche", | |||
"guitar", | |||
"chelsea", | |||
"black", | |||
"diamond", | |||
"nascar", | |||
"jackson", | |||
"cameron", | |||
"654321", | |||
"computer", | |||
"amanda", | |||
"wizard", | |||
"xxxxxxxx", | |||
"money", | |||
"phoenix", | |||
"mickey", | |||
"bailey", | |||
"knight", | |||
"iceman", | |||
"tigers", | |||
"purple", | |||
"andrea", | |||
"horny", | |||
"dakota", | |||
"aaaaaa", | |||
"player", | |||
"sunshine", | |||
"morgan", | |||
"starwars", | |||
"boomer", | |||
"cowboys", | |||
"edward", | |||
"charles", | |||
"girls", | |||
"booboo", | |||
"coffee", | |||
"xxxxxx", | |||
"bulldog", | |||
"ncc1701", | |||
"rabbit", | |||
"peanut", | |||
"john", | |||
"johnny", | |||
"gandalf", | |||
"spanky", | |||
"winter", | |||
"brandy", | |||
"compaq", | |||
"carlos", | |||
"tennis", | |||
"james", | |||
"mike", | |||
"brandon", | |||
"fender", | |||
"anthony", | |||
"blowme", | |||
"ferrari", | |||
"cookie", | |||
"chicken", | |||
"maverick", | |||
"chicago", | |||
"joseph", | |||
"diablo", | |||
"sexsex", | |||
"hardcore", | |||
"666666", | |||
"willie", | |||
"welcome", | |||
"chris", | |||
"panther", | |||
"yamaha", | |||
"justin", | |||
"banana", | |||
"driver", | |||
"marine", | |||
"angels", | |||
"fishing", | |||
"david", | |||
"maddog", | |||
"hooters", | |||
"wilson", | |||
"butthead", | |||
"dennis", | |||
"fucking", | |||
"captain", | |||
"bigdick", | |||
"chester", | |||
"smokey", | |||
"xavier", | |||
"steven", | |||
"viking", | |||
"snoopy", | |||
"blue", | |||
"eagles", | |||
"winner", | |||
"samantha", | |||
"house", | |||
"miller", | |||
"flower", | |||
"jack", | |||
"firebird", | |||
"butter", | |||
"united", | |||
"turtle", | |||
"steelers", | |||
"tiffany", | |||
"zxcvbn", | |||
"tomcat", | |||
"golf", | |||
"bond007", | |||
"bear", | |||
"tiger", | |||
"doctor", | |||
"gateway", | |||
"gators", | |||
"angel", | |||
"junior", | |||
"thx1138", | |||
"porno", | |||
"badboy", | |||
"debbie", | |||
"spider", | |||
"melissa", | |||
"booger", | |||
"1212", | |||
"flyers", | |||
"fish", | |||
"porn", | |||
"matrix", | |||
"teens", | |||
"scooby", | |||
"jason", | |||
"walter", | |||
"cumshot", | |||
"boston", | |||
"braves", | |||
"yankee", | |||
"lover", | |||
"barney", | |||
"victor", | |||
"tucker", | |||
"princess", | |||
"mercedes", | |||
"5150", | |||
"doggie", | |||
"zzzzzz", | |||
"gunner", | |||
"horney", | |||
"bubba", | |||
"2112", | |||
"fred", | |||
"johnson", | |||
"xxxxx", | |||
"tits", | |||
"member", | |||
"boobs", | |||
"donald", | |||
"bigdaddy", | |||
"bronco", | |||
"penis", | |||
"voyager", | |||
"rangers", | |||
"birdie", | |||
"trouble", | |||
"white", | |||
"topgun", | |||
"bigtits", | |||
"bitches", | |||
"green", | |||
"super", | |||
"qazwsx", | |||
"magic", | |||
"lakers", | |||
"rachel", | |||
"slayer", | |||
"scott", | |||
"2222", | |||
"asdf", | |||
"video", | |||
"london", | |||
"7777", | |||
"marlboro", | |||
"srinivas", | |||
"internet", | |||
"action", | |||
"carter", | |||
"jasper", | |||
"monster", | |||
"teresa", | |||
"jeremy", | |||
"11111111", | |||
"bill", | |||
"crystal", | |||
"peter", | |||
"pussies", | |||
"cock", | |||
"beer", | |||
"rocket", | |||
"theman", | |||
"oliver", | |||
"prince", | |||
"beach", | |||
"amateur", | |||
"7777777", | |||
"muffin", | |||
"redsox", | |||
"star", | |||
"testing", | |||
"shannon", | |||
"murphy", | |||
"frank", | |||
"hannah", | |||
"dave", | |||
"eagle1", | |||
"11111", | |||
"mother", | |||
"nathan", | |||
"raiders", | |||
"steve", | |||
"forever", | |||
"angela", | |||
"viper", | |||
"ou812", | |||
"jake", | |||
"lovers", | |||
"suckit", | |||
"gregory", | |||
"buddy", | |||
"whatever", | |||
"young", | |||
"nicholas", | |||
"lucky", | |||
"helpme", | |||
"jackie", | |||
"monica", | |||
"midnight", | |||
"college", | |||
"baby", | |||
"cunt", | |||
"brian", | |||
"mark", | |||
"startrek", | |||
"sierra", | |||
"leather", | |||
"232323", | |||
"4444", | |||
"beavis", | |||
"bigcock", | |||
"happy", | |||
"sophie", | |||
"ladies", | |||
"naughty", | |||
"giants", | |||
"booty", | |||
"blonde", | |||
"fucked", | |||
"golden", | |||
"0", | |||
"fire", | |||
"sandra", | |||
"pookie", | |||
"packers", | |||
"einstein", | |||
"dolphins", | |||
"chevy", | |||
"winston", | |||
"warrior", | |||
"sammy", | |||
"slut", | |||
"8675309", | |||
"zxcvbnm", | |||
"nipples", | |||
"power", | |||
"victoria", | |||
"asdfgh", | |||
"vagina", | |||
"toyota", | |||
"travis", | |||
"hotdog", | |||
"paris", | |||
"rock", | |||
"xxxx", | |||
"extreme", | |||
"redskins", | |||
"erotic", | |||
"dirty", | |||
"ford", | |||
"freddy", | |||
"arsenal", | |||
"access14", | |||
"wolf", | |||
"nipple", | |||
"iloveyou", | |||
"alex", | |||
"florida", | |||
"eric", | |||
"legend", | |||
"movie", | |||
"success", | |||
"rosebud", | |||
"jaguar", | |||
"great", | |||
"cool", | |||
"cooper", | |||
"1313", | |||
"scorpio", | |||
"mountain", | |||
"madison", | |||
"987654", | |||
"brazil", | |||
"lauren", | |||
"japan", | |||
"naked", | |||
"squirt", | |||
"stars", | |||
"apple", | |||
"alexis", | |||
"aaaa", | |||
"bonnie", | |||
"peaches", | |||
"jasmine", | |||
"kevin", | |||
"matt", | |||
"qwertyui", | |||
"danielle", | |||
"beaver", | |||
"4321", | |||
"4128", | |||
"runner", | |||
"swimming", | |||
"dolphin", | |||
"gordon", | |||
"casper", | |||
"stupid", | |||
"shit", | |||
"saturn", | |||
"gemini", | |||
"apples", | |||
"august", | |||
"3333", | |||
"canada", | |||
"blazer", | |||
"cumming", | |||
"hunting", | |||
"kitty", | |||
"rainbow", | |||
"112233", | |||
"arthur", | |||
"cream", | |||
"calvin", | |||
"shaved", | |||
"surfer", | |||
"samson", | |||
"kelly", | |||
"paul", | |||
"mine", | |||
"king", | |||
"racing", | |||
"5555", | |||
"eagle", | |||
"hentai", | |||
"newyork", | |||
"little", | |||
"redwings", | |||
"smith", | |||
"sticky", | |||
"cocacola", | |||
"animal", | |||
"broncos", | |||
"private", | |||
"skippy", | |||
"marvin", | |||
"blondes", | |||
"enjoy", | |||
"girl", | |||
"apollo", | |||
"parker", | |||
"qwert", | |||
"time", | |||
"sydney", | |||
"women", | |||
"voodoo", | |||
"magnum", | |||
"juice", | |||
"abgrtyu", | |||
"777777", | |||
"dreams", | |||
"maxwell", | |||
"music", | |||
"rush2112", | |||
"russia", | |||
"scorpion", | |||
"rebecca", | |||
"tester", | |||
"mistress", | |||
"phantom", | |||
"billy", | |||
"6666", | |||
"albert" | |||
]; | |||
$index = array_search($search, $worst_password_list); | |||
if ($index === FALSE) { | |||
return false; | |||
} else { | |||
return $index + 1; | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
auxiliary.org-netbeans-modules-html-editor-lib.default-html-public-id=-//W3C//DTD HTML 4.01 Transitional//EN | |||
include.path=${php.global.include.path} | |||
php.version=PHP_70 | |||
source.encoding=UTF-8 | |||
src.dir=. | |||
tags.asp=false | |||
tags.short=false | |||
web.root=. |
@@ -0,0 +1,9 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project xmlns="http://www.netbeans.org/ns/project/1"> | |||
<type>org.netbeans.modules.php.project</type> | |||
<configuration> | |||
<data xmlns="http://www.netbeans.org/ns/php-project/1"> | |||
<name>WebAppTemplate</name> | |||
</data> | |||
</configuration> | |||
</project> |
@@ -0,0 +1,11 @@ | |||
<?php | |||
// List of pages and metadata | |||
define("PAGES", [ | |||
"home" => [ | |||
"title" => "home" | |||
], | |||
"404" => [ | |||
"title" => "404 error" | |||
] | |||
]); |
@@ -0,0 +1,5 @@ | |||
<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 class="alert alert-warning"><b><?php lang("404 error");?></b><br /> <?php lang("page not found"); ?></div> | |||
</div> | |||
</div> |
@@ -0,0 +1 @@ | |||
<h1>Hello World</h1> |
@@ -0,0 +1,226 @@ | |||
<?php | |||
/** | |||
* This file contains global settings and utility functions. | |||
*/ | |||
ob_start(); // allow sending headers after content | |||
// Unicode, solves almost all stupid encoding problems | |||
header('Content-Type: text/html; charset=utf-8'); | |||
// l33t $ecurity h4x | |||
header('X-Content-Type-Options: nosniff'); | |||
header('X-XSS-Protection: 1; mode=block'); | |||
header('X-Powered-By: Late-night coding frenzies (plz send caffeine, thx)'); | |||
$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 | |||
require __DIR__ . '/lang/messages.php'; | |||
// text strings (i18n) | |||
require __DIR__ . '/lang/' . LANGUAGE . ".php"; | |||
/** | |||
* Kill off the running process and spit out an error message | |||
* @param string $error error message | |||
*/ | |||
function sendError($error) { | |||
die("<!DOCTYPE html><html><head><title>Error</title></head><body><h1 style='color: red; font-family: sans-serif; font-size:100%;'>" . htmlspecialchars($error) . "</h1></body></html>"); | |||
} | |||
date_default_timezone_set(TIMEZONE); | |||
// Database settings | |||
// Also inits database and stuff | |||
use Medoo\Medoo; | |||
$database; | |||
try { | |||
$database = new Medoo([ | |||
'database_type' => DB_TYPE, | |||
'database_name' => DB_NAME, | |||
'server' => DB_SERVER, | |||
'username' => DB_USER, | |||
'password' => DB_PASS, | |||
'charset' => DB_CHARSET | |||
]); | |||
} catch (Exception $ex) { | |||
//header('HTTP/1.1 500 Internal Server Error'); | |||
sendError("Database error. Try again later. $ex"); | |||
} | |||
if (!DEBUG) { | |||
error_reporting(0); | |||
} else { | |||
error_reporting(E_ALL); | |||
ini_set('display_errors', 'On'); | |||
} | |||
$VARS; | |||
if ($_SERVER['REQUEST_METHOD'] === 'POST') { | |||
$VARS = $_POST; | |||
define("GET", false); | |||
} else { | |||
$VARS = $_GET; | |||
define("GET", true); | |||
} | |||
/** | |||
* Checks if a string or whatever is empty. | |||
* @param $str The thingy to check | |||
* @return boolean True if it's empty or whatever. | |||
*/ | |||
function is_empty($str) { | |||
return (is_null($str) || !isset($str) || $str == ''); | |||
} | |||
/** | |||
* I18N string getter. If the key doesn't exist, outputs the key itself. | |||
* @param string $key I18N string key | |||
* @param boolean $echo whether to echo the result or return it (default echo) | |||
*/ | |||
function lang($key, $echo = true) { | |||
if (array_key_exists($key, STRINGS)) { | |||
$str = STRINGS[$key]; | |||
} else { | |||
$str = $key; | |||
} | |||
if ($echo) { | |||
echo $str; | |||
} else { | |||
return $str; | |||
} | |||
} | |||
/** | |||
* I18N string getter (with builder). If the key doesn't exist, outputs the key itself. | |||
* @param string $key I18N string key | |||
* @param array $replace key-value array of replacements. | |||
* If the string value is "hello {abc}" and you give ["abc" => "123"], the | |||
* result will be "hello 123". | |||
* @param boolean $echo whether to echo the result or return it (default echo) | |||
*/ | |||
function lang2($key, $replace, $echo = true) { | |||
if (array_key_exists($key, STRINGS)) { | |||
$str = STRINGS[$key]; | |||
} else { | |||
$str = $key; | |||
} | |||
foreach ($replace as $find => $repl) { | |||
$str = str_replace("{" . $find . "}", $repl, $str); | |||
} | |||
if ($echo) { | |||
echo $str; | |||
} else { | |||
return $str; | |||
} | |||
} | |||
/** | |||
* Checks if an email address is valid. | |||
* @param string $email Email to check | |||
* @return boolean True if email passes validation, else false. | |||
*/ | |||
function isValidEmail($email) { | |||
return filter_var($email, FILTER_VALIDATE_EMAIL); | |||
} | |||
/** | |||
* Hashes the given plaintext password | |||
* @param String $password | |||
* @return String the hash, using bcrypt | |||
*/ | |||
function encryptPassword($password) { | |||
return password_hash($password, PASSWORD_BCRYPT); | |||
} | |||
/** | |||
* Securely verify a password and its hash | |||
* @param String $password | |||
* @param String $hash the hash to compare to | |||
* @return boolean True if password OK, else false | |||
*/ | |||
function comparePassword($password, $hash) { | |||
return password_verify($password, $hash); | |||
} | |||
function dieifnotloggedin() { | |||
if ($_SESSION['loggedin'] != true) { | |||
sendError("Session expired. Please log out and log in again."); | |||
} | |||
} | |||
/** | |||
* Check if the previous database action had a problem. | |||
* @param array $specials int=>string array with special response messages for SQL errors | |||
*/ | |||
function checkDBError($specials = []) { | |||
global $database; | |||
$errors = $database->error(); | |||
if (!is_null($errors[1])) { | |||
foreach ($specials as $code => $text) { | |||
if ($errors[1] == $code) { | |||
sendError($text); | |||
} | |||
} | |||
sendError("A database error occurred:<br /><code>" . $errors[2] . "</code>"); | |||
} | |||
} | |||
/* | |||
* http://stackoverflow.com/a/20075147/2534036 | |||
*/ | |||
if (!function_exists('base_url')) { | |||
function base_url($atRoot = FALSE, $atCore = FALSE, $parse = FALSE) { | |||
if (isset($_SERVER['HTTP_HOST'])) { | |||
$http = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http'; | |||
$hostname = $_SERVER['HTTP_HOST']; | |||
$dir = str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); | |||
$core = preg_split('@/@', str_replace($_SERVER['DOCUMENT_ROOT'], '', realpath(dirname(__FILE__))), NULL, PREG_SPLIT_NO_EMPTY); | |||
$core = $core[0]; | |||
$tmplt = $atRoot ? ($atCore ? "%s://%s/%s/" : "%s://%s/") : ($atCore ? "%s://%s/%s/" : "%s://%s%s"); | |||
$end = $atRoot ? ($atCore ? $core : $hostname) : ($atCore ? $core : $dir); | |||
$base_url = sprintf($tmplt, $http, $hostname, $end); | |||
} else | |||
$base_url = 'http://localhost/'; | |||
if ($parse) { | |||
$base_url = parse_url($base_url); | |||
if (isset($base_url['path'])) | |||
if ($base_url['path'] == '/') | |||
$base_url['path'] = ''; | |||
} | |||
return $base_url; | |||
} | |||
} | |||
function redirectToPageId($id, $args, $dontdie) { | |||
header('Location: ' . URL . '?id=' . $id . $args); | |||
if (is_null($dontdie)) { | |||
die("Please go to " . URL . '?id=' . $id . $args); | |||
} | |||
} | |||
function redirectIfNotLoggedIn() { | |||
if ($_SESSION['loggedin'] !== TRUE) { | |||
header('Location: ' . URL . '/login.php'); | |||
die(); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
<?php | |||
// Whether to show debugging data in output. | |||
// DO NOT SET TO TRUE IN PRODUCTION!!! | |||
define("DEBUG", false); | |||
// Database connection settings | |||
// See http://medoo.in/api/new for info | |||
define("DB_TYPE", "mysql"); | |||
define("DB_NAME", "app"); | |||
define("DB_SERVER", "localhost"); | |||
define("DB_USER", "app"); | |||
define("DB_PASS", ""); | |||
define("DB_CHARSET", "utf8"); | |||
define("SITE_TITLE", "Web App Template"); | |||
// Used to identify the system in OTP and other places | |||
define("SYSTEM_NAME", "Web App Template"); | |||
// For supported values, see http://php.net/manual/en/timezones.php | |||
define("TIMEZONE", "America/Denver"); | |||
// Base URL for site links. | |||
define('URL', 'http://localhost:8000/'); | |||
// See lang folder for language options | |||
define('LANGUAGE', "en_us"); | |||
// Minimum length for new passwords | |||
// The system checks new passwords against the 500 worst passwords and rejects | |||
// any matches. | |||
// If you want to have additional password requirements, go edit action.php. | |||
// However, all that does is encourage people to use the infamous | |||
// "post-it password manager". See also https://xkcd.com/936/ and | |||
// http://stackoverflow.com/a/34166252/2534036 for reasons why forcing passwords | |||
// like CaPs45$% is not actually a great idea. | |||
// Encourage users to use 2-factor auth whenever possible. | |||
define("MIN_PASSWORD_LENGTH", 8); | |||
////////////////////////////////////////////////////////////// | |||
// /!\ Warning: Changing these values may /!\ // | |||
// /!\ violate the terms of your license agreement! /!\ // | |||
////////////////////////////////////////////////////////////// | |||
define("LICENSE_TEXT", "<b>Free Software: MIT License</b>"); | |||
define("COPYRIGHT_NAME", "Netsyms Technologies"); | |||
////////////////////////////////////////////////////////////// |
@@ -0,0 +1,13 @@ | |||
.banner-image { | |||
max-height: 100px; | |||
margin: 2em auto; | |||
} | |||
.navbar-brand { | |||
font-size: 110%; | |||
} | |||
.footer { | |||
margin-top: 10em; | |||
text-align: center; | |||
} |
@@ -0,0 +1,7 @@ | |||
$(document).ready(function () { | |||
/* Fade out alerts */ | |||
$(".alert .close").click(function (e) { | |||
$(this).parent().fadeOut('slow'); | |||
}); | |||
}); |