Use HTTP error codes, better error handling

This commit is contained in:
Miraty 2022-05-20 02:19:45 +02:00
parent f05d1a6764
commit c890421454
25 changed files with 70 additions and 108 deletions

View File

@ -12,11 +12,13 @@ define("OPTIONS_PASSWORD", array(
));
function checkPasswordFormat($password) {
return preg_match("/" . PASSWORD_REGEX . "/", $password);
if (preg_match("/" . PASSWORD_REGEX . "/", $password) !== true)
userError("Password malformed.")
}
function checkUsernameFormat($username) {
return preg_match("/" . USERNAME_REGEX . "/", $username);
if (preg_match("/" . USERNAME_REGEX . "/", $username) !== true)
userError("Username malformed.")
}
function hashPassword($password) {

View File

@ -14,3 +14,13 @@ if (SERVICE !== "")
// Page titles definition
require "pages.php";
function userError($msg) {
http_response_code(422);
exit("<strong>User error<strong>: The server refused to process this request: <em>" . $msg . "</em>");
}
function serverError($msg) {
http_response_code(500);
exit("<strong>Server error<strong>: The server encountered an error: <em>" . $msg . "</em>");
}

View File

@ -4,7 +4,7 @@ require "init.php";
function antiCSRF() {
if (!isset($_SERVER['HTTP_SEC_FETCH_SITE']) OR $_SERVER['HTTP_SEC_FETCH_SITE'] !== "same-origin")
exit("ERROR: Anti-CSRF verification failed ! (Wrong or unset Sec-Fetch-Site HTTP header)");
userError("Anti-CSRF verification failed ! (Wrong or unset Sec-Fetch-Site HTTP header)");
}
// Session initialisation (with cookies)

View File

@ -16,7 +16,6 @@ CREATE TABLE IF NOT EXISTS "users" (
"id" INTEGER NOT NULL UNIQUE,
"username" TEXT NOT NULL,
"password" TEXT NOT NULL,
"sftp_enabled" INTEGER NOT NULL,
"registration_date" INTEGER NOT NULL,
PRIMARY KEY("id" AUTOINCREMENT)
);

15
dns.php
View File

@ -1,18 +1,21 @@
<?php
function checkIpFormat($ip) {
if (!filter_var($ip, FILTER_VALIDATE_IP))
exit("ERROR: wrong IP address");
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE))
exit("ERROR: IP address is on the private range");
userError("IP address is on the private range.");
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE))
exit("ERROR: IP address is on the reserved range");
userError("IP address is on the reserved range.");
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
return "A";
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
return "AAAA";
userError("IP address malformed.");
}
function checkAbsoluteDomainFormat($domain) {
// If the domain must end with a dot
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR !preg_match("/^([a-z0-9_-]{1,63}\.){2,127}$/", $domain))
exit("ERROR: wrong domain");
userError("Domain malformed.");
}
function checkAction($action) {
@ -21,5 +24,5 @@ function checkAction($action) {
else if ($action === "add")
return "";
else
exit("ERROR: wrong value for action");
userError("Wrong value for action.");
}

30
ht.php
View File

@ -3,7 +3,7 @@
function checkDomainFormat($domain) {
// If the domain must end without a dot
if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR !preg_match("/^([a-z0-9_-]{1,63}\.){1,126}[a-z0-9]{1,63}$/", $domain))
exit("ERROR: wrong domain");
userError("Wrong domain.");
}
function addNiverLog($message, $outputLines, $returnCode = false) {
@ -82,34 +82,6 @@ function listDbDirs($username, $domainType, $protocol) {
return false;
}
function sftpStatus($username) {
$db = new PDO('sqlite:' . DB_PATH);
$usernameArr[0] = $username;
$op = $db->prepare('SELECT sftp_enabled FROM users WHERE username = ?');
$op->execute($usernameArr);
$status = $op->fetch()['sftp_enabled'];
if ($status == "0") {
return false;
} else if ($status == "1") {
return true;
} else {
exit("Wrong value for sftp_enabled");
}
}
function enableSftp($username) {
$db = new PDO('sqlite:' . DB_PATH);
$op = $db->prepare("UPDATE users SET sftp_enabled = 1 WHERE username = :username");
$op->bindParam(':username', $username);
$op->execute();
}
function selectSites($username, $domainType, $protocol, $onlyLeAvailable) {
$db = new PDO('sqlite:' . DB_PATH);
$usernameArray[0] = $username;

4
ns.php
View File

@ -26,7 +26,7 @@ function nsParseCommonRequirements() {
$values['ttl'] = $_POST['ttl-value'] * $_POST['ttl-multiplier'];
if (!($values['ttl'] >= 300 AND $values['ttl'] <= 432000))
exit("Erreur : le TTL doit être compris entre 5 minutes et 5 jours (entre 300 et 432000 secondes)");
userError("Le TTL doit être compris entre 5 minutes et 5 jours (entre 300 et 432000 secondes).");
return $values;
}
@ -77,5 +77,5 @@ function nsCheckZonePossession($submittedZone) {
}
// If there is no entry in the database for the user matching the submitted zone
exit("ERROR: You don't own this zone on the nameserver");
userError("You don't own this zone on the nameserver.");
}

View File

@ -20,11 +20,9 @@ if (isset($_POST['username']) AND isset($_POST['password'])) {
antiCSRF();
if (!checkPasswordFormat($_POST['password']))
exit("Le format du mot de passe n'est pas valide !");
checkPasswordFormat($_POST['password']);
if (!checkUsernameFormat($_POST['username']))
exit("Le format du nom du compte n'est pas valide !");
checkUsernameFormat($_POST['username']);
if (checkPassword($_POST['username'], $_POST['password'])) {
@ -37,11 +35,10 @@ if (isset($_POST['username']) AND isset($_POST['password'])) {
if (preg_match("/^[0-9a-z\/-]+$/", $_GET['redir']))
header("Location: " . CONF['common']['prefix'] . "/" . $_GET['redir']);
else
exit("ERROR : Wrong character in redir argument");
userError("Wrong character in <code>redir</code>.");
} else {
header("Location: " . CONF['common']['prefix'] . "/");
}
exit;
} else {
echo "<br>Connexion impossible : mot de passe invalide";
}

View File

@ -20,10 +20,9 @@ if (isset($_SESSION['username']) AND isset($_POST['newPassword']) AND isset($_PO
antiCSRF();
if (checkPassword($_SESSION['username'], $_POST['currentPassword'])) {
checkPasswordFormat($_POST['newPassword']);
if (!checkPasswordFormat($_POST['newPassword']))
exit("Erreur : Le format du nouveau mot de passe n'est pas bon !");
if (checkPassword($_SESSION['username'], $_POST['currentPassword'])) {
$username = $_SESSION['username'];
$newPassword = password_hash($_POST['newPassword'], PASSWORD_DEFAULT);

View File

@ -6,11 +6,9 @@ if (isset($_POST['username']) AND isset($_POST['password'])) {
antiCSRF();
if (!checkPasswordFormat($_POST['password']))
exit("Le format du mot de passe n'est pas valide !");
checkPasswordFormat($_POST['password']);
if (!checkUsernameFormat($_POST['username']))
exit("Le format du nom du compte n'est pas valide !");
checkUsernameFormat($_POST['username']);
$username = $_POST['username'];
$userExist = userExist($username);
@ -18,17 +16,17 @@ if (isset($_POST['username']) AND isset($_POST['password'])) {
// Setup SFTP directory
umask(0002);
if (!mkdir(CONF['ht']['ht_path'] . "/" . $username, 0775))
exit("ERROR: Can't create directory");
if (mkdir(CONF['ht']['ht_path'] . "/" . $username, 0775) !== true)
serverError("Can't create user directory.");
exec(CONF['ht']['sudo_path'] . " " . CONF['ht']['chgrp_path'] . " " . CONF['ht']['sftpgo_group'] . " " . CONF['ht']['ht_path'] . "/" . $username, $stdout, $code);
if ($code !== 0)
exit("ERROR: Can't change group");
serverError("Can't change user directory group.");
$password = hashPassword($_POST['password']);
$db = new PDO('sqlite:' . DB_PATH);
$stmt = $db->prepare("INSERT INTO users(username, password, sftp_enabled, registration_date) VALUES(:username, :password, 0, :registration_date)");
$stmt = $db->prepare("INSERT INTO users(username, password, registration_date) VALUES(:username, :password, :registration_date)");
$time = date("Y-m-d H:i:s");
@ -39,7 +37,6 @@ if (isset($_POST['username']) AND isset($_POST['password'])) {
$stmt->execute();
$_SESSION['username'] = $username;
$_SESSION['sftp_enabled'] = false;
header('Location: ' . CONF['common']['prefix'] . '/');
exit;
}

View File

@ -55,7 +55,7 @@ if (isset($_POST['dir']) AND isset($_SESSION['username'])) {
antiCSRF();
if (!in_array($_POST['dir'], $notYetEnabledDirs))
exit("ERROR : Wrong value for dir");
userError("Wrong value for <code>dir</code>.");
// Generate a .onion address
$torConf = file_get_contents(CONF['ht']['tor_config_path']);
@ -78,7 +78,7 @@ HiddenServicePort 80 [::1]:" . CONF['ht']['internal_onion_http_port'] . "
$onion = file_get_contents(CONF['ht']['ht_path'] . "/" . $_SESSION['username'] . "/" . $_POST['dir'] . "/hostname");
$onion = str_replace(array("\r", "\n"), "", $onion);
if (preg_match("/[0-9a-z]{56}\.onion/", $onion) !== 1)
exit("ERROR: No onion address found");
serverError("No onion address found.");
// Store it in the database
addSite($_SESSION['username'], $_POST['dir'], $onion, "onion", "http");

View File

@ -65,7 +65,7 @@ if (isset($_POST['domain']) AND isset($_POST['dir']) AND isset($_SESSION['userna
checkDomainFormat($_POST['domain']);
if (!in_array($_POST['dir'], $notYetEnabledDirs))
exit("ERROR : Wrong value for dir");
userError("Wrong value for <code>dir</code>.");
addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "http");

View File

@ -31,7 +31,7 @@ if (isset($_POST['domain']) AND isset($_SESSION['username'])) {
// Abort if Certbot failed
if ($returnCode !== 0)
exit("Let's Encrypt certificate obtention failed. Try again later, or contact an administrator.");
serverError("Certbot failed to get a Let's Encrypt certificate.");
// Replace self-signed certificate by Let's Encrypt certificate in Nginx configuration
$conf = file_get_contents(CONF['ht']['nginx_config_path'] . "/" . $_POST['domain'] . ".conf");
@ -44,7 +44,7 @@ if (isset($_POST['domain']) AND isset($_SESSION['username'])) {
// Abort if Nginx reload failed
if ($returnCode !== 0)
exit("Nginx configuration reload failed. Try again later, or contact an administrator.");
serverError("Nginx configuration reload failed.");
echo "Succès : La connexion avec votre site utilise désomais un certificat TLS émis par Let's Encrypt.";
}

View File

@ -31,13 +31,13 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!($_POST['flag'] >= 0 AND $_POST['flag'] <= 255))
exit("ERROR: Wrong value for flag");
userError("Wrong value for <code>flag</code>.");
if (!(preg_match("/^[a-z]{1,127}$/", $_POST['tag'])))
exit("ERROR: Wrong value for tag");
userError("Wrong value for <code>tag</code>.");
if (!(preg_match("/^[a-z0-9.-]{1,255}$/", $_POST['value'])))
exit("ERROR: Wrong value for value");
userError("Wrong value for <code>value</code>.");
exec(CONF['ns']['knotc_path'] . " zone-begin " . $_POST['zone']);
exec(CONF['ns']['knotc_path'] . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN CAA " . $_POST['flag'] . " " . $_POST['tag'] . " " . $_POST['value']);

View File

@ -35,7 +35,7 @@ if (isset($_POST['zone']) AND isset($_SESSION['username'])) {
$found = preg_match("#\n" . preg_quote($_POST['zone']) . "\s+0\s+CDS\s+([0-9]{1,5})\s+([0-9]{1,2})\s+([0-9])\s+([0-9A-F]{64})\n#", $zoneContent, $matches);
if ($found !== 1)
exit("ERROR: Unable to get public key record from zone file");
serverError("Unable to get public key record from zone file.");
$tag = $matches[1];
$algo = $matches[2];

View File

@ -19,14 +19,7 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
checkIpFormat($_POST['ip']);
if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
$record = "A";
else if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
$record = "AAAA";
else
exit("ERROR: unknown IP format");
$record = checkIpFormat($_POST['ip']);
exec(CONF['ns']['knotc_path'] . " zone-begin " . $_POST['zone']);
exec(CONF['ns']['knotc_path'] . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN " . $record . " " . $_POST['ip']);

View File

@ -31,13 +31,13 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!($_POST['flag'] >= 0 AND $_POST['flag'] <= 255))
exit("ERROR: Wrong value for flag");
userError("Wrong value for <code>flag</code>.");
if (!(preg_match("/^[a-z]{1,127}$/", $_POST['tag'])))
exit("ERROR: Wrong value for tag");
userError("Wrong value for <code>tag</code>.");
if (!(preg_match("/^[a-z0-9.-]{1,255}$/", $_POST['value'])))
exit("ERROR: Wrong value for value");
userError("Wrong value for <code>value</code>.");
exec(CONF['ns']['knotc_path'] . " zone-begin " . $_POST['zone']);
exec(CONF['ns']['knotc_path'] . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN CAA " . $_POST['flag'] . " " . $_POST['tag'] . " " . $_POST['value']);

View File

@ -30,7 +30,7 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 255))
exit("ERROR: Wrong value for priority");
userError("Wrong value for <code>priority</code>.");
checkAbsoluteDomainFormat($_POST['host']);

View File

@ -44,13 +44,13 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 65535))
exit("ERROR: Wrong value for priority");
userError("Wrong value for <code>priority</code>.");
if (!($_POST['weight'] >= 0 AND $_POST['weight'] <= 65535))
exit("ERROR: Wrong value for weight");
userError("Wrong value for <code>weight</code>.");
if (!($_POST['port'] >= 0 AND $_POST['port'] <= 65535))
exit("ERROR: Wrong value for port");
userError("Wrong value for <code>port</code>.");
checkAbsoluteDomainFormat($_POST['target']);

View File

@ -43,13 +43,13 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!($_POST['algo'] === "1" OR $_POST['algo'] === "3" OR $_POST['algo'] === "4"))
exit("ERROR: Wrong value for algo");
userError("Wrong value for <code>algo</code>.");
if (!($_POST['type'] === "2"))
exit("ERROR: Wrong value for type");
userError("Wrong value for <code>type</code>.");
if (!(preg_match("/^[a-z0-9]{64}$/", $_POST['fp'])))
exit("ERROR: Wrong value for fp");
userError("Wrong value for <code>fp</code>.");
exec(CONF['ns']['knotc_path'] . " zone-begin " . $_POST['zone']);
exec(CONF['ns']['knotc_path'] . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN SSHFP " . $_POST['algo'] . " " . $_POST['type'] . " " . $_POST['fp']);

View File

@ -54,16 +54,16 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!($_POST['use'] >= 0 AND $_POST['use'] <= 3))
exit("ERROR: Wrong value for use");
userError("Wrong value for <code>use</code>.");
if (!($_POST['selector'] === "0" OR $_POST['selector'] === "1"))
exit("ERROR: Wrong value for selector");
userError("Wrong value for <code>selector</code>.");
if (!($_POST['type'] >= 0 OR $_POST['type'] <= 2))
exit("ERROR: Wrong value for type");
userError("Wrong value for <code>type</code>.");
if (!(preg_match("/^[a-zA-Z0-9.-]{1,1024}$/", $_POST['content'])))
exit("ERROR: Wrong value for content");
userError("Wrong value for <code>content</code>.");
exec(CONF['ns']['knotc_path'] . " zone-begin " . $_POST['zone']);
exec(CONF['ns']['knotc_path'] . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN TLSA " . $_POST['use'] . " " . $_POST['selector'] . " " . $_POST['type'] . " " . $_POST['content']);

View File

@ -18,7 +18,7 @@ if (nsCommonRequirements()
$values = nsParseCommonRequirements();
if (!(preg_match("/^[a-zA-Z0-9 =:!%$+\/\()[\]_-]{5,8192}$/", $_POST['txt'])))
exit("ERROR : Wrong caracter or wrong caracter quantity");
userError("Wrong value for <code>txt</code>.");
exec(CONF['ns']['knotc_path'] . " zone-begin " . $_POST['zone']);
exec(CONF['ns']['knotc_path'] . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . ' IN TXT \"' . $_POST['txt'] . '\"');

View File

@ -78,14 +78,14 @@ if (isset($_POST['zone']) AND isset($_POST['keytag']) AND isset($_POST['algo'])
AND !($_POST['algo'] === "15")
AND !($_POST['algo'] === "16")
)
exit("Wrong value for algo");
userError("Wrong value for <code>algo</code>.");
$_POST['keytag'] = intval($_POST['keytag']);
if ((!preg_match("/^[0-9]{1,6}$/", $_POST['keytag'])) OR !($_POST['keytag'] >= 1) OR !($_POST['keytag'] <= 65535))
exit("Wrong value for keytag");
userError("Wrong value for <code>keytag</code>.");
if (!$_POST['dt'] === "2" AND !$_POST['dt'] === "4")
exit("Wrong value for dt");
userError("Wrong value for <code>dt</code>.");
checkAbsoluteDomainFormat($_POST['zone']);
nsCheckZonePossession($_POST['zone']);

View File

@ -45,24 +45,14 @@ if (isset($_POST['action']) AND isset($_POST['subdomain']) AND isset($_POST['suf
antiCSRF();
if (!$suffixes)
exit("ERROR : You don't own any domain");
if (!in_array($_POST['suffix'], $suffixes))
exit("ERROR : You don't own this suffix");
if (in_array($_POST['suffix'], $suffixes) !== true)
userError("You don't own this domain.");
$domain = $_POST['subdomain'] . "." . $_POST['suffix'];
checkAbsoluteDomainFormat($domain);
checkIpFormat($_POST['ip']);
if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
$record = "A";
else if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
$record = "AAAA";
else
exit("Unknown error about IP format");
$record = checkIpFormat($_POST['ip']);
$action = checkAction($_POST['action']);

View File

@ -53,7 +53,7 @@ function regCheckDomainPossession($domain) {
}
if (!($owned === true))
exit("Erreur : Vous ne possédez pas ce domaine sur le registre !");
userError("You don't own this domain.");
}
function regIsFree($domain) {