diff --git a/common/init.php b/common/init.php index 93fb94e..b835dc6 100644 --- a/common/init.php +++ b/common/init.php @@ -6,6 +6,10 @@ define("SERVICE", substr(dirname($_SERVER['PHP_SELF']), strlen(CONF['common']['p define("PAGE", basename($_SERVER['PHP_SELF'], '.php')); define("DB_PATH", CONF['common']['root_path'] . "/db/niver.db"); // Niver's SQLite database +define("PLACEHOLDER_DOMAIN", "example"); // From RFC2606: Reserved Top Level DNS Names > 2. TLDs for Testing, & Documentation Examples +define("PLACEHOLDER_IPV6", "2001:db8::3"); // From RFC3849: IPv6 Address Prefix Reserved for Documentation +define("PLACEHOLDER_IPV4", "203.0.113.42"); // From RFC5737: IPv4 Address Blocks Reserved for Documentation + // Page titles definition require "pages.php"; diff --git a/common/pages.php b/common/pages.php index eecab92..50cbfb4 100644 --- a/common/pages.php +++ b/common/pages.php @@ -92,12 +92,18 @@ switch (SERVICE) { case "mkdir": $page['title'] = "Créer un dossier de site"; break; - case "http-onion": - $page['title'] = "Accès HTTP par service Onion"; + case "add-http-onion": + $page['title'] = "Ajouter un accès HTTP par Onion"; break; - case "https-domain": - $page['title'] = "Accès HTTP par DNS et TLS"; + case "add-http-dns": + $page['title'] = "Ajouter un accès HTTP par DNS+TLS"; break; + case "del-http-onion": + $page['title'] = "Retirer un accès HTTP par Onion"; + break; + case "del-http-dns": + $page['title'] = "Retirer un accès HTTP par DNS+TLS"; + break; case "le": $page['title'] = "Installer un certificat Let's Encrypt"; break; diff --git a/fn/auth.php b/fn/auth.php index 40e3f95..e428c82 100644 --- a/fn/auth.php +++ b/fn/auth.php @@ -76,8 +76,8 @@ function changePassword($username, $password) { $stmt = $db->prepare("UPDATE users SET password = :password WHERE username = :username"); - $stmt->bindParam(':username', $username); - $stmt->bindParam(':password', $password); + $stmt->bindValue(':username', $username); + $stmt->bindValue(':password', $password); $stmt->execute(); } diff --git a/fn/common.php b/fn/common.php index 04a2f21..1525f03 100644 --- a/fn/common.php +++ b/fn/common.php @@ -22,3 +22,33 @@ function switchToFormProcess($requireLogin = true) { if ($requireLogin AND !isset($_SESSION['username'])) userError("Vous devez être connecté·e pour effectuer cette action."); } + +function query($action, $table, $conditions = [], $column = NULL) { + + $query = match ($action) { + 'select' => 'SELECT *', + 'delete' => 'DELETE', + }; + + $query .= " FROM $table"; + + foreach ($conditions as $key => $val) { + if ($key === array_key_first($conditions)) + $query .= " WHERE $key = :$key"; + else + $query .= " AND $key = :$key"; + } + + $db = new PDO('sqlite:' . DB_PATH); + + $op = $db->prepare($query); + + foreach ($conditions as $key => $val) + $op->bindValue(":$key", $val); + + $op->execute(); + + if (isset($column)) + return array_column($op->fetchAll(PDO::FETCH_ASSOC), $column); + return $op->fetchAll(PDO::FETCH_ASSOC); +} diff --git a/fn/dns.php b/fn/dns.php index fe5cf00..6476942 100644 --- a/fn/dns.php +++ b/fn/dns.php @@ -1,9 +1,5 @@ 2. TLDs for Testing, & Documentation Examples -define("PLACEHOLDER_IPV6", "2001:db8::3"); // From RFC3849: IPv6 Address Prefix Reserved for Documentation -define("PLACEHOLDER_IPV4", "203.0.113.42"); // From RFC5737: IPv4 Address Blocks Reserved for Documentation - function knotcExec($suffix, $cmd) { $action = checkAction($_POST['action']); diff --git a/fn/ht.php b/fn/ht.php index b85921b..048ca4d 100644 --- a/fn/ht.php +++ b/fn/ht.php @@ -8,7 +8,7 @@ function checkDomainFormat($domain) { function listFsDirs($username) { $absoluteDirs = glob(CONF['ht']['ht_path'] . "/" . $username . "/*/", GLOB_ONLYDIR); - $dirs = array(); + $dirs = []; foreach ($absoluteDirs as $absoluteDir) if (preg_match("/^[a-z0-9-]{1,32}$/", basename($absoluteDir))) array_push($dirs, basename($absoluteDir)); @@ -20,69 +20,30 @@ function addSite($username, $siteDir, $domain, $domainType, $protocol) { $op = $db->prepare("INSERT INTO sites(username, site_dir, domain, domain_type, protocol, creation_date, le_enabled) VALUES(:username, :site_dir, :domain, :domain_type, :protocol, :creation_date, :le_enabled)"); - $time = date("Y-m-d H:i:s"); if ($domainType === "dns" AND $protocol === "http") $le_enabled = 0; else $le_enabled = NULL; - $op->bindParam(':username', $username); - $op->bindParam(':site_dir', $siteDir); - $op->bindParam(':domain', $domain); - $op->bindParam(':domain_type', $domainType); - $op->bindParam(':protocol', $protocol); - $op->bindParam(':creation_date', $time); - $op->bindParam(':le_enabled', $le_enabled); + $op->bindValue(':username', $username); + $op->bindValue(':site_dir', $siteDir); + $op->bindValue(':domain', $domain); + $op->bindValue(':domain_type', $domainType); + $op->bindValue(':protocol', $protocol); + $op->bindValue(':creation_date', date("Y-m-d H:i:s")); + $op->bindValue(':le_enabled', $le_enabled); $op->execute(); } -function listDbDirs($username, $domainType, $protocol) { - $db = new PDO('sqlite:' . DB_PATH); - - $op = $db->prepare('SELECT site_dir FROM sites WHERE username = :username AND domain_type = :domain_type AND protocol = :protocol'); - $op->bindParam(':username', $username); - $op->bindParam(':domain_type', $domainType); - $op->bindParam(':protocol', $protocol); - $op->execute(); - - return array_column($op->fetchAll(PDO::FETCH_ASSOC), 'site_dir'); -} - function dirsStatuses($username, $domainType, $protocol) { - $dirs = array(); - $fsDirs = listFsDirs($username); - $dbUsedDirs = listDbDirs($username, $domainType, $protocol); - foreach ($fsDirs as $fsDir) - $dirs[$fsDir] = ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)); + $dbDirs = query('select', 'sites', [ + 'username' => $username, + 'domain_type' => $domainType, + 'protocol' => $protocol, + ], 'site_dir'); + $dirs = []; + foreach (listFsDirs($username) as $fsDir) + $dirs[$fsDir] = in_array($fsDir, $dbDirs); return $dirs; } - -function selectSites($username, $domainType, $protocol, $onlyLeAvailable) { - $db = new PDO('sqlite:' . DB_PATH); - - $query = "SELECT site_dir,domain FROM sites WHERE username = :username AND domain_type = :domain_type AND protocol = :protocol"; - - if ($onlyLeAvailable === true) - $query = $query . " AND le_enabled = 0"; - - $op = $db->prepare($query); - $op->bindParam(':username', $username); - $op->bindParam(':domain_type', $domainType); - $op->bindParam(':protocol', $protocol); - $op->execute(); - - $i = 0; - $entry = $op->fetch(); - while (isset($entry['site_dir'])) { - $result[$i]["siteDir"] = $entry['site_dir']; - $result[$i]["domain"] = $entry['domain']; - $i++; - $entry = $op->fetch(); - } - - if (isset($result)) - return $result; - else - return false; -} diff --git a/fn/ns.php b/fn/ns.php index a7860d8..d63c87c 100644 --- a/fn/ns.php +++ b/fn/ns.php @@ -27,35 +27,12 @@ function nsParseCommonRequirements() { } function nsListUserZones($username) { - $db = new PDO('sqlite:' . DB_PATH); - $usernameArray[0] = $username; - - $op = $db->prepare('SELECT zone FROM zones WHERE username = ?'); - $op->execute($usernameArray); - - $zones = array(); - foreach ($op->fetchAll() as $zone) - array_push($zones, $zone['zone']); - - return $zones; + return query('select', 'zones', ['username' => $username], 'zone'); } function nsCheckZonePossession($submittedZone) { checkAbsoluteDomainFormat($submittedZone); - $db = new PDO('sqlite:' . DB_PATH); - $username[0] = $_SESSION['username']; - - $op = $db->prepare('SELECT zone FROM zones WHERE username = ?'); - $op->execute($username); - - $dbZone = $op->fetch()['zone']; - - while ($dbZone != NULL) { - if ($dbZone === $submittedZone) return; - $dbZone = $op->fetch()['zone']; - } - - // If there is no entry in the database for the user matching the submitted zone - userError("You don't own this zone on the nameserver."); + if (!in_array($submittedZone, query('select', 'zones', ['username' => $_SESSION['username']], 'zone'), true)) + userError("You don't own this zone on the nameserver."); } diff --git a/fn/reg.php b/fn/reg.php index 2156eba..5c5e423 100644 --- a/fn/reg.php +++ b/fn/reg.php @@ -12,7 +12,7 @@ function regListUserDomains($username) { $op = $db->prepare('SELECT domain FROM registry WHERE username = ?'); $op->execute($usernameArray); - $domains = array(); + $domains = []; foreach ($op->fetchAll() as $domain) array_push($domains, $domain['domain']); diff --git a/public/auth/register.php b/public/auth/register.php index f0b3e5a..303bbf6 100644 --- a/public/auth/register.php +++ b/public/auth/register.php @@ -40,17 +40,13 @@ exec(CONF['ht']['sudo_path'] . " " . CONF['ht']['chgrp_path'] . " " . CONF['ht'] if ($code !== 0) 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, registration_date) VALUES(:username, :password, :registration_date)"); -$time = date("Y-m-d H:i:s"); - -$stmt->bindParam(':username', $_POST['username']); -$stmt->bindParam(':password', $password); -$stmt->bindParam(':registration_date', $time); +$stmt->bindValue(':username', $_POST['username']); +$stmt->bindValue(':password', hashPassword($_POST['password'])); +$stmt->bindValue(':registration_date', date("Y-m-d H:i:s")); $stmt->execute(); diff --git a/public/ht/https-domain.php b/public/ht/add-http-dns.php similarity index 100% rename from public/ht/https-domain.php rename to public/ht/add-http-dns.php diff --git a/public/ht/http-onion.php b/public/ht/add-http-onion.php similarity index 100% rename from public/ht/http-onion.php rename to public/ht/add-http-onion.php diff --git a/public/ht/del-http-onion.php b/public/ht/del-http-onion.php new file mode 100644 index 0000000..40ecc61 --- /dev/null +++ b/public/ht/del-http-onion.php @@ -0,0 +1,74 @@ + +
+Ajouter un accès en .onion sur un dossier +
+ + + +dir."); + +// Delete Tor config +$torConf = file_get_contents(CONF['ht']['tor_config_path']); +if ($torConf === false) + serverError("Failed to read current Tor configuration."); +$torConf = str_replace("HiddenServiceDir " . CONF['ht']['tor_keys_path'] . "/" . $_POST['dir'] . "/ +HiddenServicePort 80 [::1]:" . CONF['ht']['internal_onion_http_port'] . " +", "", $torConf); +if (file_put_contents(CONF['ht']['tor_config_path'], $torConf) === false) + serverError("Failed to write new Tor configuration."); + +// Reload Tor +exec(CONF['ht']['sudo_path'] . " " . CONF['ht']['systemctl_path'] . " reload " . CONF['ht']['tor_service'], $output, $code); +if ($code !== 0) + serverError("Failed to reload Tor."); + +// Delete Nginx config +$onion = query('select', 'sites', [ + 'username' => $_SESSION['username'], + 'domain_type' => 'onion', + 'protocol' => 'http', + 'site_dir' => $_POST['dir'], +], 'domain')[0]; +if (unlink(CONF['ht']['nginx_config_path'] . "/" . $onion . ".conf") !== true) + serverError("Failed to delete Nginx configuration."); + +// Reload Nginx +exec(CONF['ht']['sudo_path'] . " " . CONF['ht']['systemctl_path'] . " reload nginx", result_code: $code); +if ($code !== 0) + serverError("Failed to reload Nginx."); + +// Delete from database +query('delete', 'sites', [ + 'username' => $_SESSION['username'], + 'domain_type' => 'onion', + 'protocol' => 'http', + 'site_dir' => $_POST['dir'], +]); + +success("Accès retiré avec succès."); diff --git a/public/ht/index.php b/public/ht/index.php index a0bdd88..2b96bc0 100644 --- a/public/ht/index.php +++ b/public/ht/index.php @@ -53,13 +53,21 @@