Added PGP Two Factor Authentication (2FA)

This commit is contained in:
Daniel Winzen
2020-02-17 07:07:02 +01:00
parent e949e4ea48
commit c2b010e8e6
14 changed files with 287 additions and 187 deletions

View File

@ -6,16 +6,8 @@ session_start(['name'=>'hosting_admin']);
if($_SERVER['REQUEST_METHOD']==='HEAD'){
exit; // headers sent, no further processing needed
}
print_header('Admin panel', 'td{padding:5px;}', '_blank');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Admin panel</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="'.CANONICAL_URL. $_SERVER['SCRIPT_NAME'] .'">
<style>td{padding:5px;}</style>
<base target="_blank">
</head><body>
<h1>Hosting - Admin panel</h1>
<?php
$error=false;

View File

@ -17,14 +17,8 @@ if($_SERVER['REQUEST_METHOD']==='POST'){
}
}
header('Content-Type: text/html; charset=UTF-8');
print_header('Delete account');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Delete account</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
<p>This will delete your account and all data asociated with it. It can't be un-done. Are you sure?</p>
<?php echo $msg; ?>
<form method="POST" action="delete.php"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><table>

View File

@ -2,16 +2,10 @@
require('../common.php');
header('Content-Type: text/html; charset=UTF-8');
header('X-Accel-Expires: 60');
print_header('FAQ');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - FAQ</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
<h1>Hosting - Info</h1>
<p><a href="index.php">Info</a> | <a href="register.php">Register</a> | <a href="login.php">Login</a> | <a href="list.php">List of hosted sites</a> | FAQ</p>
<h1>Hosting - FAQ</h1>
<?php main_menu('faq.php'); ?>
<table border="1">
<tr><th>Question</th><th>Answer</th></tr>
<tr><td>Your rules are so strict. Can't you make an exception for my site?</td><td>No, I will not make exceptions for any site and neither am I corruptible by offering me money. Once I start making an exception for your site, I would have to for every other site as well which is the same as if the rules didn't exist.</td></tr>

View File

@ -274,17 +274,7 @@ if($sort==='M'){
if($order==='D'){
$list=array_reverse($list);
}
$dir=htmlspecialchars($dir);
?>
<!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
<title><?php echo htmlspecialchars(SITE_NAME); ?> - FileManager - Index of <?php echo $dir; ?></title>
<style type="text/css">.list td:nth-child(3){word-break:break-all;} .list td:nth-child(5){text-align:right;} .list tr{height:28px;}
$style = '.list td:nth-child(3){word-break:break-all;} .list td:nth-child(5){text-align:right;} .list tr{height:28px;}
.back{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPH/AAAAADMzM2ZmZpmZmSH5BAUAAAQALAAAAAAUABYAAANLSLrc/oKE8CoZM1O7os7c9WmcN04WdoKQdBIANypAHG5YbS/7kus1RlDxA+p4xqSRpmwCKE7nINqMwKi6wEAY1VaS3tBV/OiRz4sEADs=);}
.dir{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPH/AAAAADMzM5lmM//MmSH5BAUAAAQALAAAAAAUABYAAANUSLrc/jDKSRm4+E4wuu9AxH1kpimAQHpqiQ5CLMcrHI71GgdXngs8nI8F7A1JReFxZzyygk4iNNpJUmFWmFbF3cJ4hNRsPA6Aw+a0es0LLEzwjDsBADs=);}
.img{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPMLAAAAADMzM2YAAAAzZmZmZv8zMwCZMwCZzJmZmczMzP///wAAAAAAAAAAAAAAAAAAACH5BAUAAAsALAAAAAAUABYAAASQMMhJ57p4BcW730F2bV5JhhlZdio6KkUsF4mi2tg2y4ICBL/gaxfrAY5IwJDY4yCeCKUGNjNYDTUFVKqTGTgJa1bLVSRi3/CVlIi+EgIB9mrdJAbuaYe+ThzwZSx8BAEHf3k3CQFXhIaHgR2KE46PLytmlJV6JX6ZgJYedwOjpJ+blyWIAVCsrU9AGUmys1IRADs=);}
@ -295,9 +285,10 @@ $dir=htmlspecialchars($dir);
.bin{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPIFAAAAADMzM5mZmczMzP///wAAAAAAAAAAACH5BAUAAAUALAAAAAAUABYAAANpGLq89bAEQqudIb4JABkdMBATqXFeR6ilCaFr6rWuFN8qEOj8doOdUWjosxgpgqQA4AOKbhUl05aTHZe+KtSCpVpVxu7EKfSEp7TjOeshX9E469obf7Prc5g7r+6LA0qBgkk7EUOHiFMJADs=);}
.doc{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPL/AAAAADMzM/8zM5lmM//MM2bM/5mZmf///yH5BAUAAAgALAAAAAAUABYAAARvMMhJJ7oYhcO730F2bV5JhtlZceSBjixBFDT7YedMFxwQ+ECYa1c7AI5IgDAwaDY9hqhBqWE5n9AotVXqHqZCbxdcNSbPHTJXnN72zsl2mC0vcwTmOEdNL/E7eHB1a3R/fXtbAVKLjFE/GXCRSBcRADs=);}
.txt{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPH/AAAAADMzM5mZmf///yH5BAUAAAQALAAAAAAUABYAAANYGLq89JCEQaudIb5pO88R11UiuI3XBXFA61JAEM8nCrtujbeW4AuAmq3yC0puuxcFKBwSjaykcsA8OntQpPTZvFZF2un3iu1ul1kyuuv8Bn7wuE8WkdqNCQA7);}
.sh{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPH/AAAAADMzM5mZmf///yH5BAUAAAQALAAAAAAUABYAAANgGLq89JCEQaudIb5pO88R11UiuFXAkJIXxAEwjAYATZ9UuuZxjPc7imAoAOBUyBHRKBk5hUzR01L8AXuVanPa0b6usWyU2x2rwDLokTzw8tDiNdnNVksCxLx+eIOg0Q8JADs=);}
</style>
</head><body>
.sh{min-width:22px; background:no-repeat url(data:img/gif;base64,R0lGODlhFAAWAPH/AAAAADMzM5mZmf///yH5BAUAAAQALAAAAAAUABYAAANgGLq89JCEQaudIb5pO88R11UiuFXAkJIXxAEwjAYATZ9UuuZxjPc7imAoAOBUyBHRKBk5hUzR01L8AXuVanPa0b6usWyU2x2rwDLokTzw8tDiNdnNVksCxLx+eIOg0Q8JADs=);}';
print_header('FileManager - Index of '.$dir, $style);
$dir=htmlspecialchars($dir);
?>
<h1>Index of <?php echo $dir; ?></h1>
<?php if($dir!=='/'){ ?>
<p>Upload up to 1GB and up to 100 files at once <form action="files.php" enctype="multipart/form-data" method="post"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>"><input name="files[]" type="file" multiple><input type="hidden" name="path" value="<?php echo $dir; ?>"><input type="submit" value="Upload"></form></p><br>
@ -376,24 +367,15 @@ function get_properties($name, &$icon, &$size){
function send_not_found(){
header("HTTP/1.1 404 Not Found");
echo '<!DOCTYPE html><html><head>';
echo '<title>404 Not Found</title>';
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
echo '<meta name=viewport content="width=device-width, initial-scale=1">';
echo '<link rel="canonical" href="'.CANONICAL_URL . $_SERVER['SCRIPT_NAME'].'">';
echo '</head><body>';
print_header('FileManager - 404 Not Found');
echo '<p>The requested file '.htmlspecialchars($_REQUEST['path']).' was not found on your account.</p>';
echo '<p><a href="files.php">Go back to home directory</a>.</p>';
echo '</body></html>';
}
function send_login(){
print_header('FileManager - Login');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - FileManager - Login</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name=viewport content="width=device-width, initial-scale=1">
</head><body>
<p>Please type in your system account password: <form action="files.php" method="post"><input name="ftp_pass" type="password" autofocus><input type="submit" value="Login"></form></p>
<p><a href="home.php">Go back to dashboard</a>.</p>
</body></html>
@ -437,11 +419,7 @@ function ftp_recursive_delete($ftp, $file){
}
function send_rename($dir){
echo '<!DOCTYPE html><html><head>';
echo '<title>' . htmlspecialchars(SITE_NAME) . ' - FileManager - Rename file</title>';
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
echo '<meta name=viewport content="width=device-width, initial-scale=1">';
echo '</head><body>';
print_header('FileManager - Rename file');
echo '<form action="files.php" method="post">';
echo '<input type="hidden" name="csrf_token" value="'.$_SESSION['csrf_token'].'">';
echo '<input type="hidden" name="path" value="'.htmlspecialchars($dir).'">';
@ -456,11 +434,7 @@ function send_rename($dir){
}
function send_edit($ftp, $dir){
echo '<!DOCTYPE html><html><head>';
echo '<title>' . htmlspecialchars(SITE_NAME) . ' - FileManager - Edit file</title>';
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
echo '<meta name=viewport content="width=device-width, initial-scale=1">';
echo '</head><body>';
print_header('FileManager - Edit file');
echo '<form action="files.php" method="post">';
echo '<input type="hidden" name="csrf_token" value="'.$_SESSION['csrf_token'].'">';
echo '<input type="hidden" name="path" value="'.htmlspecialchars($dir).'">';

View File

@ -12,14 +12,9 @@ if(isset($_POST['action']) && $_POST['action']==='add_db'){
if(isset($_POST['action']) && $_POST['action']==='del_db' && !empty($_POST['db'])){
if($error=check_csrf_error()){
die($error);
} ?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Delete database</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
}
print_header('Delete database');
?>
<p>This will delete your database <?php echo htmlspecialchars($_POST['db']); ?> and all data asociated with it. It can't be un-done. Are you sure?</p>
<form method="post" action="home.php"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="db" value="<?php echo htmlspecialchars($_POST['db']); ?>">
@ -38,14 +33,9 @@ if(isset($_POST['action']) && $_POST['action']==='del_db_2' && !empty($_POST['db
if(isset($_POST['action']) && $_POST['action']==='del_onion' && !empty($_POST['onion'])){
if($error=check_csrf_error()){
die($error);
} ?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Delete onion domain</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
}
print_header('Delete onion domain');
?>
<p>This will delete your onion domain <?php echo htmlspecialchars($_POST['onion']); ?>.onion and all data asociated with it. It can't be un-done. Are you sure?</p>
<form method="post" action="home.php"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="onion" value="<?php echo htmlspecialchars($_POST['onion']); ?>">
@ -119,14 +109,9 @@ if(isset($_POST['action']) && $_POST['action']==='add_domain' && !empty($_POST['
if(isset($_POST['action']) && $_POST['action']==='del_domain' && !empty($_POST['domain'])){
if($error=check_csrf_error()){
die($error);
} ?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Delete domain</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
}
print_header('Delete domain');
?>
<p>This will delete your domain <?php echo htmlspecialchars($_POST['domain']); ?> and all data asociated with it. It can't be un-done. Are you sure?</p>
<form method="post" action="home.php"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<input type="hidden" name="domain" value="<?php echo htmlspecialchars($_POST['domain']); ?>">
@ -183,18 +168,8 @@ if(isset($_REQUEST['action']) && isset($_POST['domain']) && $_POST['action']==='
enqueue_instance_reload();
}
}
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Dashboard</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
<style type="text/css">#custom_onion:not(checked)+#private_key{display:none;}#custom_onion:checked+#private_key{display:block;}</style>
<style>td{padding:5px}meter{width:200px}</style>
</head><body>
<p>Logged in as <?php echo htmlspecialchars($user['username']); ?> <a href="logout.php">Logout</a> | <a href="password.php">Change passwords</a> | <a target="_blank" href="files.php">FileManager</a> | <a href="delete.php">Delete account</a></p>
<?php
print_header('Dashboard', '#custom_onion:not(checked)+#private_key{display:none;}#custom_onion:checked+#private_key{display:block;}td{padding:5px}meter{width:200px}');
dashboard_menu($user, 'home.php');
if(!empty($msg)){
echo $msg;
}

View File

@ -2,16 +2,10 @@
require('../common.php');
header('Content-Type: text/html; charset=UTF-8');
header('X-Accel-Expires: 60');
print_header('Info');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
<h1>Hosting - Info</h1>
<p>Info | <a href="register.php">Register</a> | <a href="login.php">Login</a> | <a href="list.php">List of hosted sites</a> | <a href="faq.php">FAQ</a></p>
<?php main_menu('index.php'); ?>
<p>Here you can get yourself a free web hosting account on my server.</p>
<h2>What you get:</h2>
<ul>
@ -29,8 +23,9 @@ header('X-Accel-Expires: 60');
<li>Webmail and IMAP, POP3 and SMTP access to your mail account</li>
<li>Your own .onion domains</li>
<li>Clearnet domains or a free subdomain of danwin1210.me</li>
<li>There is a missing feature or you need a special configuration? Just <a href="https://danwin1210.me/contact.php">contact me</a> and I'll see what I can do.</li>
<li>Empty/Unused accounts will be automatically deleted after a month of inactivity</li>
<li>PGP based Two Factor Authentication (2FA)</li>
<li>There is a missing feature or you need a special configuration? Just <a href="https://danwin1210.me/contact.php">contact me</a> and I'll see what I can do.</li>
<li>More to come…</li>
</ul>
<h2>Rules</h2>

View File

@ -3,19 +3,11 @@ require_once('../common.php');
header('Content-Type: text/html; charset=UTF-8');
header('X-Accel-Expires: 60');
$db = get_db_instance();
print_header('List of hosted sites', 'td{padding:5px;}', '_blank');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - List of hosted sites</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
<style>td{padding:5px;}</style>
<base rel="noopener" target="_blank">
</head><body>
<h1>Hosting - List of hosted sites</h1>
<p><a href="index.php" target="_self">Info</a> | <a href="register.php" target="_self">Register</a> | <a href="login.php" target="_self">Login</a> | List of hosted sites | <a href="faq.php" target="_self">FAQ</a></p>
<?php
main_menu('list.php');
$stmt=$db->query('SELECT COUNT(*) FROM users WHERE public=1;');
$count=$stmt->fetch(PDO::FETCH_NUM);
$stmt=$db->query('SELECT COUNT(*) FROM users WHERE public=0;');

View File

@ -8,64 +8,117 @@ if(!empty($_SESSION['hosting_username']) && empty($_SESSION['2fa_code'])){
}
$msg='';
$username='';
$pgp_key='';
$tfa=0;
if(!empty($_SESSION['hosting_username'])){
$tfa = $_SESSION['tfa'];
$pgp_key = $_SESSION['pgp_key'];
}
if($_SERVER['REQUEST_METHOD']==='POST'){
$db = get_db_instance();
$ok=true;
if($error=check_captcha_error()){
$msg.="<p style=\"color:red;\">$error</p>";
$ok=false;
}elseif(!isset($_POST['username']) || $_POST['username']===''){
$msg.='<p style="color:red;">Error: username may not be empty.</p>';
$ok=false;
}else{
$stmt=$db->prepare('SELECT username, password, id FROM users WHERE username=?;');
$stmt->execute([$_POST['username']]);
$tmp=[];
if(($tmp=$stmt->fetch(PDO::FETCH_NUM))===false && preg_match('/^([2-7a-z]{16}).onion$/', $_POST['username'], $match)){
$stmt=$db->prepare('SELECT users.username, users.password, users.id FROM users INNER JOIN onions ON (onions.user_id=users.id) WHERE onions.onion=?;');
$stmt->execute([$match[1]]);
$tmp=$stmt->fetch(PDO::FETCH_NUM);
if(!empty($_SESSION['hosting_username'])){
if(!empty($_POST['2fa_code']) && $_POST['2fa_code'] === $_SESSION['2fa_code']){
unset($_SESSION['2fa_code']);
unset($_SESSION['pgp_key']);
unset($_SESSION['tfa']);
session_write_close();
header('Location: home.php');
exit;
}else{
$msg.='<p style="color:red">Wrong 2FA code</p>';
}
if($tmp){
$username=$tmp[0];
$password=$tmp[1];
$stmt=$db->prepare('SELECT new_account.approved FROM new_account INNER JOIN users ON (users.id=new_account.user_id) WHERE users.id=?;');
$stmt->execute([$tmp[2]]);
if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
if(REQUIRE_APPROVAL && !$tmp[0]){
$msg.='<p style="color:red;">Error: Your account is pending admin approval. Please try again later.</p>';
}else{
$msg.='<p style="color:red;">Error: Your account is pending creation. Please try again in a minute.</p>';
} else {
$db = get_db_instance();
$ok=true;
if($error=check_captcha_error()){
$msg.="<p style=\"color:red;\">$error</p>";
$ok=false;
}elseif(!isset($_POST['username']) || $_POST['username']===''){
$msg.='<p style="color:red;">Error: username may not be empty.</p>';
$ok=false;
}else{
$stmt=$db->prepare('SELECT username, password, id, tfa, pgp_key FROM users WHERE username=?;');
$stmt->execute([$_POST['username']]);
$tmp=[];
if(($tmp=$stmt->fetch(PDO::FETCH_ASSOC))===false && preg_match('/^([2-7a-z]{16}).onion$/', $_POST['username'], $match)){
$stmt=$db->prepare('SELECT users.username, users.password, users.id, users.tfa, users.pgp_key FROM users INNER JOIN onions ON (onions.user_id=users.id) WHERE onions.onion=?;');
$stmt->execute([$match[1]]);
$tmp=$stmt->fetch(PDO::FETCH_ASSOC);
}
if($tmp){
$username=$tmp['username'];
$password=$tmp['password'];
$tfa=$tmp['tfa'];
$pgp_key=$tmp['pgp_key'];
$stmt=$db->prepare('SELECT new_account.approved FROM new_account INNER JOIN users ON (users.id=new_account.user_id) WHERE users.id=?;');
$stmt->execute([$tmp['id']]);
if($tmp=$stmt->fetch(PDO::FETCH_NUM)){
if(REQUIRE_APPROVAL && !$tmp[0]){
$msg.='<p style="color:red;">Error: Your account is pending admin approval. Please try again later.</p>';
}else{
$msg.='<p style="color:red;">Error: Your account is pending creation. Please try again in a minute.</p>';
}
$ok=false;
}elseif(!isset($_POST['pass']) || !password_verify($_POST['pass'], $password)){
$msg.='<p style="color:red;">Error: wrong password.</p>';
$ok=false;
}
$ok=false;
}elseif(!isset($_POST['pass']) || !password_verify($_POST['pass'], $password)){
$msg.='<p style="color:red;">Error: wrong password.</p>';
}else{
$msg.='<p style="color:red;">Error: username was not found. If you forgot it, you can enter youraccount.onion instead.</p>';
$ok=false;
}
}else{
$msg.='<p style="color:red;">Error: username was not found. If you forgot it, you can enter youraccount.onion instead.</p>';
$ok=false;
}
if($ok){
$_SESSION['hosting_username']=$username;
$_SESSION['csrf_token']=sha1(uniqid());
if($tfa){
$code = bin2hex(random_bytes(3));
$_SESSION['2fa_code'] = $code;
$_SESSION['pgp_key'] = $pgp_key;
$_SESSION['tfa'] = $tfa;
} else {
session_write_close();
header('Location: home.php');
exit;
}
}
}
if($ok){
$_SESSION['hosting_username']=$username;
$_SESSION['csrf_token']=sha1(uniqid());
session_write_close();
header('Location: home.php');
}
print_header('Login');
if($tfa){
$gpg = gnupg_init();
gnupg_seterrormode($gpg, GNUPG_ERROR_WARNING);
gnupg_setarmor($gpg, 1);
$imported_key = gnupg_import($gpg, $pgp_key);
if($imported_key){
$key_info = gnupg_keyinfo($gpg, $imported_key['fingerprint']);
foreach($key_info as $key){
if($key['can_encrypt']){
foreach($key['subkeys'] as $subkey){
gnupg_addencryptkey($gpg, $subkey['fingerprint']);
}
}
}
$encrypted = gnupg_encrypt($gpg, "To login, please enter the following code to confirm ownership of your key:\n\n".$_SESSION['2fa_code']."\n");
echo $msg;
echo "<p>To login, please decrypt the following PGP encrypted message and confirm the code:</p>";
echo "<pre>$encrypted</pre>";
?>
<form action="login.php" method="post"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<table border="1">
<tr><td><input type="text" name="2fa_code"></td><td><button type="submit">Confirm</button></td></tr>
</table></form>
<p>Don't have the private key at hand? <a href="logout.php">Logout</a></p>
</body></html>
<?php
exit;
}
}
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Login</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
</head><body>
<h1>Hosting - Login</h1>
<p><a href="index.php">Info</a> | <a href="register.php">Register</a> | Login | <a href="list.php">List of hosted sites</a> | <a href="faq.php">FAQ</a></p>
<?php echo $msg; ?>
<?php
main_menu('login.php');
echo $msg;
?>
<form method="POST" action="login.php"><table>
<tr><td>Username</td><td><input type="text" name="username" value="<?php
if(isset($_POST['username'])){

View File

@ -36,13 +36,7 @@ if($_SERVER['REQUEST_METHOD']==='POST'){
}
}
header('Content-Type: text/html; charset=UTF-8');
echo '<!DOCTYPE html><html><head>';
echo '<title>' . htmlspecialchars(SITE_NAME) . ' - Change password</title>';
echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
echo '<meta name="author" content="Daniel Winzen">';
echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
echo '<link rel="canonical" href="' . CANONICAL_URL . $_SERVER['SCRIPT_NAME'] . '">';
echo '</head><body>';
print_header('Change password');
echo $msg;
echo '<form method="POST" action="password.php"><input type="hidden" name="csrf_token" value="'.$_SESSION['csrf_token'].'"><table>';
echo '<tr><td>Reset type:</td><td><select name="type">';

80
var/www/html/pgp.php Normal file
View File

@ -0,0 +1,80 @@
<?php
require('../common.php');
$user=check_login();
print_header('PGP 2FA');
dashboard_menu($user, 'pgp.php');
if($_SERVER['REQUEST_METHOD']==='POST'){
if($error=check_csrf_error()){
die($error);
}
if(isset($_POST['pgp_key'])){
$pgp_key = trim($_POST['pgp_key']);
$gpg = gnupg_init();
gnupg_seterrormode($gpg, GNUPG_ERROR_WARNING);
gnupg_setarmor($gpg, 1);
$imported_key = gnupg_import($gpg, $pgp_key);
if(!$imported_key){
echo "<p style=\"color:red\">There was an error importing the key</p>";
}else{
$db = get_db_instance();
$stmt = $db->prepare('UPDATE users SET pgp_key = ?, tfa = 0, pgp_verified = 0 WHERE id = ?;');
$stmt->execute([$pgp_key, $user['id']]);
$user['pgp_key'] = $pgp_key;
}
}
if(isset($_POST['enable_2fa_code'])){
if($_POST['enable_2fa_code'] !== $_SESSION['enable_2fa_code']){
echo "<p style=\"color:red\">Sorry, the code was incorrect</p>";
} else {
$db = get_db_instance();
$stmt = $db->prepare('UPDATE users SET tfa = 1, pgp_verified = 1 WHERE id = ?;');
$stmt->execute([$user['id']]);
$user['tfa'] = 1;
}
}
}
if(!empty($user['pgp_key'])){
if($user['tfa'] == '1'){
echo "<p style=\"color:green\">Yay, PGP based 2FA is enabled!</p>";
} else {
$gpg = gnupg_init();
gnupg_seterrormode($gpg, GNUPG_ERROR_WARNING);
gnupg_setarmor($gpg, 1);
$imported_key = gnupg_import($gpg, $user['pgp_key']);
if($imported_key){
$key_info = gnupg_keyinfo($gpg, $imported_key['fingerprint']);
foreach($key_info as $key){
if(!$key['can_encrypt']){
echo "<p>Sorry, this key can't be used to encrypt a message to you. Your key may have expired or has been revoked.</p>";
}else{
foreach($key['subkeys'] as $subkey){
gnupg_addencryptkey($gpg, $subkey['fingerprint']);
}
}
}
$_SESSION['enable_2fa_code'] = bin2hex(random_bytes(3));
if($encrypted = gnupg_encrypt($gpg, "To enable 2FA, please enter the following code to confirm ownership of your key:\n\n$_SESSION[enable_2fa_code]\n")){
echo "<p>To enable 2FA using your PGP key, please decrypt the following PGP encrypted message and confirm the code:</p>";
echo "<pre>$encrypted</pre>";
?>
<form action="pgp.php" method="post"><input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<table border="1">
<tr><td><input type="text" name="enable_2fa_code"></td><td><button type="submit">Confirm</button></td></tr>
</table></form>
<hr>
<?php
}
}
}
}
?>
<p>Add your PGP key for more security features like 2FA:</p>
<form action="pgp.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
<table border="1">
<tr><td><textarea name="pgp_key" rows="10" cols="50"><?php echo $user['pgp_key']; ?></textarea></td></tr>
<tr><td><button type="submit">Update PGP key</button></td></tr>
</table>
</form>
<p><a href="home.php">Go back to dashboard.</a></p>
</body></html>

View File

@ -6,18 +6,11 @@ if(!empty($_SESSION['hosting_username'])){
header('Location: home.php');
exit;
}
print_header('Register', '#custom_onion:not(checked)+#private_key{display:none;}#custom_onion:checked+#private_key{display:block;}');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Register</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
<style type="text/css">#custom_onion:not(checked)+#private_key{display:none;}#custom_onion:checked+#private_key{display:block;}</style>
</head><body>
<h1>Hosting - Register</h1>
<p><a href="index.php">Info</a> | Register | <a href="login.php">Login</a> | <a href="list.php">List of hosted sites</a> | <a href="faq.php">FAQ</a></p>
<?php
main_menu('register.php');
if($_SERVER['REQUEST_METHOD']==='POST'){
$db = get_db_instance();
$ok=true;

View File

@ -8,15 +8,8 @@ $user=check_login();
use chillerlan\QRCode\QRCode;
use chillerlan\QRCode\QROptions;
header('Content-Type: text/html; charset=UTF-8');
print_header('Upgrade account', 'td{padding:5px;}');
?>
<!DOCTYPE html><html><head>
<title><?php echo htmlspecialchars(SITE_NAME); ?> - Upgrade account</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="Daniel Winzen">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="canonical" href="<?php echo CANONICAL_URL . $_SERVER['SCRIPT_NAME']; ?>">
<style>td{padding:5px;}</style>
</head><body>
<h1>Hosting - Upgrade account</h1>
<?php
$rates = coinpayments_get_rates();