Skip to content

Commit

Permalink
Separated business logic into classes (#204)
Browse files Browse the repository at this point in the history
All backend functions now send responses in json
updated bootstrap to 3.3.7, jquery to 3.3.1

Separated client side javascript business logic into separate classes:
 * backend communication
 * accounts
 * crypto
  • Loading branch information
BenjaminHae committed Jul 9, 2018
1 parent 6fe95cb commit 2b3e13c
Show file tree
Hide file tree
Showing 52 changed files with 2,249 additions and 1,610 deletions.
4 changes: 2 additions & 2 deletions src/css/bootstrap-theme.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/css/bootstrap-theme.min.css

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions src/css/bootstrap.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/css/bootstrap.min.css

Large diffs are not rendered by default.

33 changes: 32 additions & 1 deletion src/function/ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,42 @@
header('X-Content-Type-Options: nosniff');
header('Content-Type: application/json');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
const ERROR_MESSAGE = [
'general' => 'Oops, our server run into some problems. Please refresh this page and try again.',
'config' => 'PLEASE CONFIG function/config.php before using this system!',
'PINunavailable' => 'No PIN available',
'PINwrong' => 'Wrong PIN',
'authentication' => 'AUTHENTICATION ERROR, PLEASE RELOGIN',
'parameter' => 'Parameter Error',
'session' => 'session unavailable',
'blockIP' => 'Your IP has been blocked due to malicious activity',
'blockAccount' => 'Your account has been protected due to continuous attack.', //ToDo add time
'loginFailed' => 'Username password combination is unknown',
'entryNotFound' => 'Entry not found',
'updateFailed' => 'Updating entry failed',
'signup' => 'Signup is not allowed.',
'invalidEmail' => 'Invalid E-mail address.',
'occupiedUser' => 'User name already occupied, please choose another user name.',
'occupiedEmail' => 'This E-mail has already been used.',
'fileFailed' => 'No File Can Be Downloaded',
'userWrong' => 'Wrong User',
'method' => 'Method not allowed',
];
function ajaxError($err)
{
echo json_encode(['status' => 'error', 'message' => ERROR_MESSAGE[$err]]);
die();
}
function error($msg)
{
echo json_encode(['status' => 'error', 'message' => $msg]);
die();
}
function ajaxSuccess($data = [])
{
echo json_encode(array_merge(['status' => 'success'], $data));
die();
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
error('Wrong method');
ajaxError('method');
}
1 change: 1 addition & 0 deletions src/function/basic.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function echoheader()
<link rel="shortcut icon" href="favicon.ico">
<script src="js/lib/jquery.min.js"></script>
<script src="js/lib/bootstrap.min.js"></script>
<script src="js/common/commonFunctions.js"></script>
</head>
<body>';
}
5 changes: 5 additions & 0 deletions src/function/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@
//Number of iterations for the password hashing
$PBKDF2_ITERATIONS = 64000;

//Minimal length of user passwords
$MINIMAL_PASSWORD_LENGTH = 7;
//Minimal length of user name
$MINIMAL_NAME_LENGTH = 5;

//Generating Password (those variables will be written into JavaScript)
//the default password length to be generated
$DEFAULT_LENGTH = 13;
Expand Down
25 changes: 17 additions & 8 deletions src/function/sqllink.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

$VERSION = '9.15';
$VERSION = '10.00';
require_once dirname(__FILE__).'/config.php';
function sqllink()
{
Expand Down Expand Up @@ -46,47 +46,56 @@ function checksession($link)
global $SERVER_TIMEOUT, $HOSTDOMAIN;
session_start();
if (!isset($_SESSION['loginok']) || $_SESSION['loginok'] != 1) {
session_destroy();
logout();

return false;
}
if (isset($_SERVER['HTTP_REFERER']) && ($_SERVER['HTTP_REFERER'] != '') && (strpos(strtolower($_SERVER['HTTP_REFERER']), strtolower($HOSTDOMAIN)) !== 0)) {
//Users from other sites are banned
session_destroy();
logout();

return false;
}
if (($_SERVER['REQUEST_METHOD'] == 'POST') && ($_POST['session_token'] !== $_SESSION['session_token'])) {
//Must check session_token to prevent cross-site attack
session_destroy();
logout();

return false;
}
if (!$link || !isset($_SESSION['create_time']) || $_SESSION['create_time'] + $SERVER_TIMEOUT < time()) {
session_destroy();
logout();

return false;
}
$usr = $_SESSION['user'];
$pw = $_SESSION['pwd'];
$id = $_SESSION['userid'];
if ($usr == '' || $pw == '' || $id == '') {
session_destroy();
logout();

return false;
}
$sql = 'SELECT * FROM `pwdusrrecord` WHERE `username`= ? AND `password`= ? AND `id`= ?';
$res = sqlexec($sql, [$usr, $pw, $id], $link);
$record = $res->fetch(PDO::FETCH_ASSOC);
if (!$record) {
session_destroy();
logout();

return false;
}
$_SESSION['create_time'] = time();
$_SESSION['create_time'] = time(); //Todo name this refresh time and create an absolute timeout
setcookie('ServerRenew', '1', 0, '/');

return true;
}
function logout()
{
foreach ($_SESSION as $key => $value) {
unset($_SESSION[$key]);
}
session_regenerate_id(true); //as suggested by owasp, change sessionId when changing context
session_destroy();
setcookie('ServerRenew', '-1', 0, '/');
}
$currentCookieParams = session_get_cookie_params();
session_set_cookie_params(0, $currentCookieParams['path'], $currentCookieParams['domain'], (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443, true);
2 changes: 2 additions & 0 deletions src/history.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
?>
<link rel="stylesheet" type="text/css" href="css/dataTables.bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="css/responsive.dataTables.min.css">
<script src="js/common/backend.js"></script>
<div class="container theme-showcase">
<p id="placeholder">PLEASE WAIT...</p>
<div id="maindiv" class="collapse">
<div class="page-header">
<h1>Trusted Devices</h1>
</div>
<div id="messageContainer"></div>
<table class="table" id="pinTable">
<tr><th>Device Type</th><th>Set Time</th><th>Untrust (Disable PIN)</th></tr>
</table>
Expand Down
8 changes: 2 additions & 6 deletions src/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<script src="js/crypto/aes.js"></script>
<script src="js/crypto/sha512.js"></script>
<script src="js/crypto/pbkdf2.js"></script>
<script src="js/crypto/password.js"></script>
<script src="js/setlocalstorage.js"></script>
<script src="js/common/backend.js"></script>
<script src="js/common/cryptoWrapper.js"></script>
<script src="js/index.js"></script>
<div class="container theme-showcase">
<div class="page-header">
Expand All @@ -25,10 +25,6 @@
<input type="submit" class="btn btn-lg btn-success btn-block" id="chk" value="Login" />
</div>
</form>
<span id="nouser" class="errorhint collapse textred">Username password combination is unknown<br /></span>
<span id="blockip" class="errorhint collapse textred">Your IP has been blocked due to malicious activity<br /></span>
<span id="accountban" class="errorhint collapse textred">Your account has been protected due to continuous attack. Try again in <span id="banTime"></span> seconds<br /></span>
<span id="othererror" class="errorhint collapse textred">Oops, our server run into some problems. Please refresh this page and try again.<br /></span>
<hr />
<button id="signup" class="btn btn-sm btn-default collapse" type="button">Sign Up</button>&nbsp; <button id="recover" class="btn btn-sm btn-warning" type="button">Password Recovery</button>
<hr />
Expand Down
179 changes: 179 additions & 0 deletions src/js/common/account.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
class Account {
constructor(index, name, enpassword) {
this.index = index;
this.name = name;
this.enpassword = enpassword;
this.other = {};
this.mFile = null;
this.mEncryptionWrapper = null;
}
// reads the account from a encrypted dict
static fromEncrypted(encryptionWrapper, encryptedAccount) {
return encryptionWrapper.decryptChar(encryptedAccount["name"])
.then(function(accountName) {
let account = new Account(encryptedAccount["index"], accountName, encryptedAccount["kss"]);
return account.setEncryptionWrapper(encryptionWrapper);
})
.then(function(account){
let resultPromise;
if (encryptedAccount["additional"] != "") {
//decrypt and extract json
resultPromise = encryptionWrapper.decryptChar(encryptedAccount["additional"])
.then(function(additional) {
let data = $.parseJSON(additional);
for (var x in data)
account.setOther(x, data[x]);
return account;
});
}
else {
resultPromise = Promise.resolve(account);
}
return resultPromise;
});
}

setEncryptionWrapper(wrapper) {
var self = this;
if (self.encryptionWrapper != null) {
var decryptedPassword;
var decryptedFileKey;
return self.getPassword()
.then(function(password) {
decryptedPassword = password;
if (self.hasFile()) {
return self.getFileKey();
}
else {
return "";
}
})
.then(function(fileKey) {
decryptedFileKey = fileKey;
return;
})
.then(function(){
self.mEncryptionWrapper = wrapper;
return self.setPassword(decryptedPassword);
})
.then(function() {
if (decryptedFileKey != '') {
return self.setFileKey(decryptedFileKey);
}
else {
return;
}
})
.then(function(){
return self;
});
}
else {
self.mEncryptionWrapper = wrapper;
return Promise.resolve(self);
}
}
get encryptionWrapper() {
return this.mEncryptionWrapper;
}

getEncrypted(withFile){
withFile = withFile || false;
var self = this;
let encryptedResult = { "kss":self.enpassword };
if (self.index != null)
encryptedResult["index"] = self.index;
return self.encryptionWrapper.encryptChar(self.name)
.then(function(enName) {
encryptedResult["name"] = enName;
let other = JSON.stringify(self.other);
return self.encryptionWrapper.encryptChar(other);
})
.then(function(enOther) {
encryptedResult["other"] = enOther;
if (withFile && self.hasFile()) {
encryptedResult["fk"] = self.file.key;
return self.encryptionWrapper.encryptChar(self.file.name)
.then(function(fname) {
encryptedResult["fname"] = fname;
});
}
})
.then(function(){
return encryptedResult;
});
}

get accountName() {
return this.name;
}
setAccountName(name) {
var self = this;
//reencrypt password
return self.getPassword()
.then(function(password){;
self.name = name;
return self.setPassword(password);
});
}
getPassword(){
return this.encryptionWrapper.decryptPassword(this.name, this.enpassword);
}
setPassword(password){
var self = this;
return this.encryptionWrapper.encryptPassword(this.name, password)
.then(function(enPass){
self.enpassword = enPass;
return enPass;
});
}
clearOther() {
this.other = {};
}
clearVisibleOther() {
for (let item in this.other) {
if (item.substring(0,1) != "_") {
delete this.other[item];
}
}
}
get availableOthers() {
let availableOthers = [];
for (let otherName in this.other) {
availableOthers.push(otherName);
}
return availableOthers;
}
setOther(name, value) {
this.other[name] = value;
}
getOther(name) {
return this.other[name];
}
getOtherJSON() {
return JSON.stringify(this.other);
}
addEncryptedFile(name, fkey) {
var self = this;
self.file = { "name":"", "key": fkey };
return self.encryptionWrapper.decryptChar(name)
.then(function(decryptedName) {
self.file.name = decryptedName;
return self.file;
});
}
hasFile() {
return 'file' in this;
}
getFileKey(){
return this.encryptionWrapper.decryptPassword(this.file.name, this.file.key);
}
setFileKey(key){
var self = this;
return this.encryptionWrapper.encryptPassword(this.file.name, key)
.then(function(enKey){
self.file.key = enKey;
return enKey;
});
}
}
Loading

0 comments on commit 2b3e13c

Please sign in to comment.