2 spaces > tab

This commit is contained in:
Miraty 2022-04-18 16:05:00 +02:00
parent 5e73c9fea9
commit eb4ce11c9f
43 changed files with 1929 additions and 1929 deletions

View File

@ -7,11 +7,11 @@
<a class="authButton" href="password">Changer la clé de passe</a> <a class="authButton" href="password">Changer la clé de passe</a>
<?php } else { ?> <?php } else { ?>
Vous devez être authentifié·e pour utiliser Niver Vous devez être authentifié·e pour utiliser Niver
<br> <br>
<a class="authButton" href="register">Créer un compte</a> <a class="authButton" href="register">Créer un compte</a>
<br> <br>
<a class="authButton" href="login">Se connecter</a> <a class="authButton" href="login">Se connecter</a>
<?php } ?> <?php } ?>
<?php require "../bottom.inc.php"; ?> <?php require "../bottom.inc.php"; ?>

View File

@ -1,15 +1,15 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<form method="post"> <form method="post">
<label for="username">Identifiant</label><br> <label for="username">Identifiant</label><br>
<input required="" minlength="4" maxlength="32" pattern="<?= USERNAME_REGEX ?>" id="username" name="username" type="text" placeholder="lain"> <input required="" minlength="4" maxlength="32" pattern="<?= USERNAME_REGEX ?>" id="username" name="username" type="text" placeholder="lain">
<br> <br>
<label for="password">Clé de passe</label><br> <label for="password">Clé de passe</label><br>
<input required="" autocomplete="current-password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" id="password" name="password" type="password" placeholder="************************"> <input required="" autocomplete="current-password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" id="password" name="password" type="password" placeholder="************************">
<br> <br>
<input type="submit"> <input type="submit">
</form> </form>
Pas de compte ? <a class="authButton" href="register">En créer un</a> Pas de compte ? <a class="authButton" href="register">En créer un</a>
@ -18,34 +18,34 @@ Pas de compte ? <a class="authButton" href="register">En créer un</a>
if (isset($_POST['username']) AND isset($_POST['password'])) { if (isset($_POST['username']) AND isset($_POST['password'])) {
antiCSRF(); antiCSRF();
if (!checkPasswordFormat($_POST['password'])) if (!checkPasswordFormat($_POST['password']))
exit("Le format du mot de passe n'est pas valide !"); exit("Le format du mot de passe n'est pas valide !");
if (!checkUsernameFormat($_POST['username'])) if (!checkUsernameFormat($_POST['username']))
exit("Le format du nom du compte n'est pas valide !"); exit("Le format du nom du compte n'est pas valide !");
if (checkPassword($_POST['username'], $_POST['password'])) { if (checkPassword($_POST['username'], $_POST['password'])) {
$_SESSION['username'] = htmlspecialchars($_POST['username']); $_SESSION['username'] = htmlspecialchars($_POST['username']);
$_SESSION['sftp_enabled'] = sftpStatus($_SESSION['username']); $_SESSION['sftp_enabled'] = sftpStatus($_SESSION['username']);
if (outdatedPasswordHash($_SESSION['username'])) if (outdatedPasswordHash($_SESSION['username']))
changePassword($_SESSION['username'], $_POST['password']); changePassword($_SESSION['username'], $_POST['password']);
if (isset($_GET['redir'])) { if (isset($_GET['redir'])) {
if (preg_match("/^[0-9a-z\/-]+$/", $_GET['redir'])) if (preg_match("/^[0-9a-z\/-]+$/", $_GET['redir']))
header('Location: ' . PREFIX . "/" . $_GET['redir']); header('Location: ' . PREFIX . "/" . $_GET['redir']);
else else
exit("ERROR : Wrong character in redir argument"); exit("ERROR : Wrong character in redir argument");
} else { } else {
header('Location: ' . PREFIX); header('Location: ' . PREFIX);
} }
exit; exit;
} else { } else {
echo "<br>Connexion impossible : mot de passe invalide"; echo "<br>Connexion impossible : mot de passe invalide";
} }
} }

View File

@ -1,45 +1,45 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Vous pouvez ici changer le mot de passe permettant d'accéder à votre compte Niver. Vous pouvez ici changer le mot de passe permettant d'accéder à votre compte Niver.
</p> </p>
<form method="post"> <form method="post">
<label for="currentPassword">Mot de passe actuel</label><br> <label for="currentPassword">Mot de passe actuel</label><br>
<input required="" autocomplete="current-password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" id="currentPassword" name="currentPassword" type="password" placeholder="************"><br> <input required="" autocomplete="current-password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" id="currentPassword" name="currentPassword" type="password" placeholder="************"><br>
<label for="newPassword">Nouveau mot de passe</label><br> <label for="newPassword">Nouveau mot de passe</label><br>
<input required="" autocomplete="new-password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" id="newPassword" name="newPassword" type="password" placeholder="************"><br> <input required="" autocomplete="new-password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" id="newPassword" name="newPassword" type="password" placeholder="************"><br>
<input type="submit"> <input type="submit">
</form> </form>
<?php <?php
if (isset($_SESSION['username']) AND isset($_POST['newPassword']) AND isset($_POST['currentPassword'])) { if (isset($_SESSION['username']) AND isset($_POST['newPassword']) AND isset($_POST['currentPassword'])) {
antiCSRF(); antiCSRF();
if (checkPassword($_SESSION['username'], $_POST['currentPassword'])) { if (checkPassword($_SESSION['username'], $_POST['currentPassword'])) {
if (!checkPasswordFormat($_POST['newPassword'])) if (!checkPasswordFormat($_POST['newPassword']))
exit("Erreur : Le format du nouveau mot de passe n'est pas bon !"); exit("Erreur : Le format du nouveau mot de passe n'est pas bon !");
$username = $_SESSION['username']; $username = $_SESSION['username'];
$newPassword = password_hash($_POST['newPassword'], PASSWORD_DEFAULT); $newPassword = password_hash($_POST['newPassword'], PASSWORD_DEFAULT);
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$stmt = $db->prepare("UPDATE users SET password = :password WHERE username = :username"); $stmt = $db->prepare("UPDATE users SET password = :password WHERE username = :username");
$stmt->bindParam(':username', $username); $stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $newPassword); $stmt->bindParam(':password', $newPassword);
$stmt->execute(); $stmt->execute();
} else { } else {
echo "<br>Le mot de passe actuel n'est pas bon !"; echo "<br>Le mot de passe actuel n'est pas bon !";
} }
} }

View File

@ -4,68 +4,68 @@
if (isset($_POST['username']) AND isset($_POST['password'])) { if (isset($_POST['username']) AND isset($_POST['password'])) {
antiCSRF(); antiCSRF();
if (!checkPasswordFormat($_POST['password'])) if (!checkPasswordFormat($_POST['password']))
exit("Le format du mot de passe n'est pas valide !"); exit("Le format du mot de passe n'est pas valide !");
if (!checkUsernameFormat($_POST['username'])) if (!checkUsernameFormat($_POST['username']))
exit("Le format du nom du compte n'est pas valide !"); exit("Le format du nom du compte n'est pas valide !");
$username = $_POST['username']; $username = $_POST['username'];
$userExist = userExist($username); $userExist = userExist($username);
if (!$userExist) { if (!$userExist) {
$password = hashPassword($_POST['password']); $password = hashPassword($_POST['password']);
$db = new PDO('sqlite:' . DB_PATH); $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, sftp_enabled, registration_date) VALUES(:username, :password, 0, :registration_date)");
$time = date("Y-m-d H:i:s"); $time = date("Y-m-d H:i:s");
$stmt->bindParam(':username', $username); $stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password); $stmt->bindParam(':password', $password);
$stmt->bindParam(':registration_date', $time); $stmt->bindParam(':registration_date', $time);
$stmt->execute(); $stmt->execute();
$_SESSION['username'] = $username; $_SESSION['username'] = $username;
$_SESSION['sftp_enabled'] = false; $_SESSION['sftp_enabled'] = false;
header('Location: ' . PREFIX . '/'); header('Location: ' . PREFIX . '/');
exit; exit;
} }
} }
?> ?>
<form method="post"> <form method="post">
<label for="username"> <label for="username">
<details> <details>
<summary>Identifiant</summary> <summary>Identifiant</summary>
Uniquement composé de lettres minuscules. Uniquement composé de lettres minuscules.
</details> </details>
<input id="username" minlength="4" maxlength="32" pattern="<?= USERNAME_REGEX ?>" required="" name="username" type="text" placeholder="lain"><span></span><br> <input id="username" minlength="4" maxlength="32" pattern="<?= USERNAME_REGEX ?>" required="" name="username" type="text" placeholder="lain"><span></span><br>
</label> </label>
<?php <?php
if (isset($userExist) AND $userExist == true) { if (isset($userExist) AND $userExist == true) {
echo "<br>Cet identifiant est déjà utilisé. Choisissez-en un autre."; echo "<br>Cet identifiant est déjà utilisé. Choisissez-en un autre.";
} }
?> ?>
<label for="password"> <label for="password">
<details> <details>
<summary>Clé de passe</summary> <summary>Clé de passe</summary>
Une clé de passe sécurisée est trop compliquée à deviner pour une attaque qui testerais automatiquement plein de clés de passe tout en connaissant d'autres informations et secrets sur vous. Une clé de passe sécurisée est trop compliquée à deviner pour une attaque qui testerais automatiquement plein de clés de passe tout en connaissant d'autres informations et secrets sur vous.
<br> <br>
Minimum 8 caractères si elle contient minuscule, majuscule et chiffre, ou minimum 10 caractères sinon. Minimum 8 caractères si elle contient minuscule, majuscule et chiffre, ou minimum 10 caractères sinon.
</details> </details>
<input autocomplete="new-password" id="password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" required="" name="password" type="password" placeholder="************"><span title="Le format nest pas valide"></span><br> <input autocomplete="new-password" id="password" minlength="8" maxlength="1024" pattern="<?= PASSWORD_REGEX ?>" required="" name="password" type="password" placeholder="************"><span title="Le format nest pas valide"></span><br>
</label> </label>
<input type="submit"> <input type="submit">
</form> </form>
Déjà un compte ? <a class="authButton" href="login">Se connecter</a> Déjà un compte ? <a class="authButton" href="login">Se connecter</a>

View File

@ -1,17 +1,17 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
?> ?>
</main> </main>
<footer> <footer>
<small> <small>
<?php if (isset($_SESSION['username'])) { <?php if (isset($_SESSION['username'])) {
echo "Connecté·e en tant que " . $_SESSION['username'] . "<br><a class='authButton' href='" . PREFIX . "/auth/logout'>Se déconnecter</a>"; echo "Connecté·e en tant que " . $_SESSION['username'] . "<br><a class='authButton' href='" . PREFIX . "/auth/logout'>Se déconnecter</a>";
} else { ?> } else { ?>
Vous n'êtes pas connecté·e à un compte Niver Vous n'êtes pas connecté·e à un compte Niver
<br><a class="authButton" href="<?= PREFIX ?>/auth/login?redir=<?= SERVICE ?>/<?= PAGE ?>">Se connecter</a> <br><a class="authButton" href="<?= PREFIX ?>/auth/login?redir=<?= SERVICE ?>/<?= PAGE ?>">Se connecter</a>
<?php } ?> <?php } ?>
</small> </small>
</footer> </footer>
</body> </body>
</html> </html>

View File

@ -1,87 +1,87 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Ajouter un domaine sur un dossier de site<br> Ajouter un domaine sur un dossier de site<br>
Le domaine doit pointer vers ces adresses IP : Le domaine doit pointer vers ces adresses IP :
<br>IPv4 : <code><?= IPV4_ADDRESS ?></code> <br>IPv4 : <code><?= IPV4_ADDRESS ?></code>
<br>IPv6 : <code><?= IPV6_ADDRESS ?></code> <br>IPv6 : <code><?= IPV6_ADDRESS ?></code>
</p> </p>
<form method="post"> <form method="post">
<label for="domain">Domaine sur lequel répondre</label><br> <label for="domain">Domaine sur lequel répondre</label><br>
<input required="" placeholder="capsule.<?= DOMAIN_EXAMPLE ?>" id="domain" name="domain" type="text"><br> <input required="" placeholder="capsule.<?= DOMAIN_EXAMPLE ?>" id="domain" name="domain" type="text"><br>
<label for="dir">Dossier ciblé</label><br> <label for="dir">Dossier ciblé</label><br>
<select required="" name="dir" id="dir"> <select required="" name="dir" id="dir">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$fsDirs = listFsDirs($_SESSION['username']); $fsDirs = listFsDirs($_SESSION['username']);
$dbUsedDirs = listDbDirs($_SESSION['username'], "dns", "gemini"); $dbUsedDirs = listDbDirs($_SESSION['username'], "dns", "gemini");
$i = 0; $i = 0;
$j = 0; $j = 0;
$alreadyEnabledDirs = NULL; $alreadyEnabledDirs = NULL;
$notYetEnabledDirs = NULL; $notYetEnabledDirs = NULL;
if ($fsDirs) { if ($fsDirs) {
foreach ($fsDirs as $fsDir) { foreach ($fsDirs as $fsDir) {
if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) { if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) {
$alreadyEnabledDirs[$i] = $fsDir; $alreadyEnabledDirs[$i] = $fsDir;
$i++; $i++;
} else { } else {
$notYetEnabledDirs[$j] = $fsDir; $notYetEnabledDirs[$j] = $fsDir;
$j++; $j++;
} }
} }
if (!is_null($notYetEnabledDirs)) { if (!is_null($notYetEnabledDirs)) {
foreach ($notYetEnabledDirs as $dir) { foreach ($notYetEnabledDirs as $dir) {
echo "<option value='" . $dir . "'>" . $dir . "</option>"; echo "<option value='" . $dir . "'>" . $dir . "</option>";
} }
} }
if (!is_null($alreadyEnabledDirs)) { if (!is_null($alreadyEnabledDirs)) {
foreach ($alreadyEnabledDirs as $dir) { foreach ($alreadyEnabledDirs as $dir) {
echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>"; echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>";
} }
} }
} }
?> ?>
</select> </select>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['domain']) AND isset($_POST['dir']) AND isset($_SESSION['username'])) { if (isset($_POST['domain']) AND isset($_POST['dir']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
checkDomainFormat($_POST['domain']); checkDomainFormat($_POST['domain']);
if (!in_array($_POST['dir'], $notYetEnabledDirs)) if (!in_array($_POST['dir'], $notYetEnabledDirs))
exit("ERROR : Wrong value for dir"); exit("ERROR : Wrong value for dir");
addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "gemini"); addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "gemini");
// Generate tls keys // Generate tls keys
exec(SUDO_PATH . " " . MANIVER_PATH . " gemini-new-certificate " . $_POST['domain']); exec(SUDO_PATH . " " . MANIVER_PATH . " gemini-new-certificate " . $_POST['domain']);
// Add to Twins configuration // Add to Twins configuration
$conf = " $conf = "
" . $_POST['domain'] . ": " . $_POST['domain'] . ":
cert: " . TWINS_PATH . "/tls/" . $_POST['domain'] . ".crt cert: " . TWINS_PATH . "/tls/" . $_POST['domain'] . ".crt
key: " . TWINS_PATH . "/tls/" . $_POST['domain'] . ".key key: " . TWINS_PATH . "/tls/" . $_POST['domain'] . ".key
paths: paths:
- -
path: / path: /
root: " . HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir']; root: " . HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir'];
file_put_contents(TWINS_PATH . "/twins.conf", $conf, FILE_APPEND); file_put_contents(TWINS_PATH . "/twins.conf", $conf, FILE_APPEND);
// Reload Twins daemon // Reload Twins daemon
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-twins"); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-twins");
echo "Accès par domaine ajouté sur ce dossier !"; echo "Accès par domaine ajouté sur ce dossier !";
} }
?> ?>

View File

@ -1,100 +1,100 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Ajouter un accès en .onion sur un dossier Ajouter un accès en .onion sur un dossier
</p> </p>
<form method="post"> <form method="post">
<label for="dir">Dossier ciblé</label><br> <label for="dir">Dossier ciblé</label><br>
<select required="" name="dir" id="dir"> <select required="" name="dir" id="dir">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$fsDirs = listFsDirs($_SESSION['username']); $fsDirs = listFsDirs($_SESSION['username']);
$dbUsedDirs = listDbDirs($_SESSION['username'], "onion", "gemini"); $dbUsedDirs = listDbDirs($_SESSION['username'], "onion", "gemini");
$i = 0; $i = 0;
$j = 0; $j = 0;
$alreadyEnabledDirs = NULL; $alreadyEnabledDirs = NULL;
$notYetEnabledDirs = NULL; $notYetEnabledDirs = NULL;
if ($fsDirs) { if ($fsDirs) {
foreach ($fsDirs as $fsDir) { foreach ($fsDirs as $fsDir) {
if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) { if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) {
$alreadyEnabledDirs[$i] = $fsDir; $alreadyEnabledDirs[$i] = $fsDir;
$i++; $i++;
} else { } else {
$notYetEnabledDirs[$j] = $fsDir; $notYetEnabledDirs[$j] = $fsDir;
$j++; $j++;
} }
} }
if (!is_null($notYetEnabledDirs)) { if (!is_null($notYetEnabledDirs)) {
foreach ($notYetEnabledDirs as $dir) { foreach ($notYetEnabledDirs as $dir) {
echo "<option value='" . $dir . "'>" . $dir . "</option>"; echo "<option value='" . $dir . "'>" . $dir . "</option>";
} }
} }
if (!is_null($alreadyEnabledDirs)) { if (!is_null($alreadyEnabledDirs)) {
foreach ($alreadyEnabledDirs as $dir) { foreach ($alreadyEnabledDirs as $dir) {
echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>"; echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>";
} }
} }
} }
?> ?>
</select> </select>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['dir']) AND isset($_SESSION['username'])) { if (isset($_POST['dir']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
if (!in_array($_POST['dir'], $notYetEnabledDirs)) if (!in_array($_POST['dir'], $notYetEnabledDirs))
exit("ERROR : Wrong value for dir"); exit("ERROR : Wrong value for dir");
// Generate a .onion address // Generate a .onion address
$torConf = file_get_contents(TOR_CONFIG_PATH); $torConf = file_get_contents(TOR_CONFIG_PATH);
$torConf = $torConf . "\nHiddenServiceDir " . TOR_KEYS_PATH . "/" . $_POST['dir'] . "/\nHiddenServicePort 1965 [::1]:1965"; $torConf = $torConf . "\nHiddenServiceDir " . TOR_KEYS_PATH . "/" . $_POST['dir'] . "/\nHiddenServicePort 1965 [::1]:1965";
file_put_contents(TOR_CONFIG_PATH, $torConf); file_put_contents(TOR_CONFIG_PATH, $torConf);
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-tor", $output); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-tor", $output);
addNiverLog("Tor reloaded by " . $_SESSION['username'], $output); addNiverLog("Tor reloaded by " . $_SESSION['username'], $output);
// Copy generated address to a location readable by PHP // Copy generated address to a location readable by PHP
exec(SUDO_PATH . " " . MANIVER_PATH . " export-tor " . $_SESSION['username'] . " " . $_POST['dir'], $output); exec(SUDO_PATH . " " . MANIVER_PATH . " export-tor " . $_SESSION['username'] . " " . $_POST['dir'], $output);
addNiverLog("Tor data exported by " . $_SESSION['username'], $output); addNiverLog("Tor data exported by " . $_SESSION['username'], $output);
// Wait // Wait
sleep(1); sleep(1);
// Get the address generated by Tor // Get the address generated by Tor
$onion = file_get_contents(HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir'] . "/hostname"); $onion = file_get_contents(HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir'] . "/hostname");
$onion = str_replace(array("\r", "\n"), "", $onion); $onion = str_replace(array("\r", "\n"), "", $onion);
// Store it in the database // Store it in the database
addSite($_SESSION['username'], $_POST['dir'], $onion, "onion", "gemini"); addSite($_SESSION['username'], $_POST['dir'], $onion, "onion", "gemini");
// Generate tls keys // Generate tls keys
exec(SUDO_PATH . " " . MANIVER_PATH . " gemini-new-certificate " . $onion); exec(SUDO_PATH . " " . MANIVER_PATH . " gemini-new-certificate " . $onion);
// Add to Twins configuration // Add to Twins configuration
$conf = " $conf = "
" . $onion . ": " . $onion . ":
cert: " . TWINS_PATH . "/tls/" . $onion . ".crt cert: " . TWINS_PATH . "/tls/" . $onion . ".crt
key: " . TWINS_PATH . "/tls/" . $onion . ".key key: " . TWINS_PATH . "/tls/" . $onion . ".key
paths: paths:
- -
path: / path: /
root: " . HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir']; root: " . HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir'];
file_put_contents(TWINS_PATH . "/twins.conf", $conf, FILE_APPEND); file_put_contents(TWINS_PATH . "/twins.conf", $conf, FILE_APPEND);
// Reload Twins daemon // Reload Twins daemon
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-twins"); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-twins");
// Tell the user their site address // Tell the user their site address
echo "<p>L'adresse de votre capsule Onion Gemini est : <br><a href='gemini://" . $onion . "'<code>gemini://" . $onion . "</code></a></p>"; echo "<p>L'adresse de votre capsule Onion Gemini est : <br><a href='gemini://" . $onion . "'<code>gemini://" . $onion . "</code></a></p>";
} }

View File

@ -1,94 +1,94 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Ajouter un accès en .onion sur un dossier Ajouter un accès en .onion sur un dossier
</p> </p>
<form method="post"> <form method="post">
<label for="dir">Dossier ciblé</label><br> <label for="dir">Dossier ciblé</label><br>
<select required="" name="dir" id="dir"> <select required="" name="dir" id="dir">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$fsDirs = listFsDirs($_SESSION['username']); $fsDirs = listFsDirs($_SESSION['username']);
$dbUsedDirs = listDbDirs($_SESSION['username'], "onion", "http"); $dbUsedDirs = listDbDirs($_SESSION['username'], "onion", "http");
$i = 0; $i = 0;
$j = 0; $j = 0;
$alreadyEnabledDirs = NULL; $alreadyEnabledDirs = NULL;
$notYetEnabledDirs = NULL; $notYetEnabledDirs = NULL;
if ($fsDirs) { if ($fsDirs) {
foreach ($fsDirs as $fsDir) { foreach ($fsDirs as $fsDir) {
if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) { if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) {
$alreadyEnabledDirs[$i] = $fsDir; $alreadyEnabledDirs[$i] = $fsDir;
$i++; $i++;
} else { } else {
$notYetEnabledDirs[$j] = $fsDir; $notYetEnabledDirs[$j] = $fsDir;
$j++; $j++;
} }
} }
if (!is_null($notYetEnabledDirs)) { if (!is_null($notYetEnabledDirs)) {
foreach ($notYetEnabledDirs as $dir) { foreach ($notYetEnabledDirs as $dir) {
echo "<option value='" . $dir . "'>" . $dir . "</option>"; echo "<option value='" . $dir . "'>" . $dir . "</option>";
} }
} }
if (!is_null($alreadyEnabledDirs)) { if (!is_null($alreadyEnabledDirs)) {
foreach ($alreadyEnabledDirs as $dir) { foreach ($alreadyEnabledDirs as $dir) {
echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>"; echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>";
} }
} }
} }
?> ?>
</select> </select>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['dir']) AND isset($_SESSION['username'])) { if (isset($_POST['dir']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
if (!in_array($_POST['dir'], $notYetEnabledDirs)) if (!in_array($_POST['dir'], $notYetEnabledDirs))
exit("ERROR : Wrong value for dir"); exit("ERROR : Wrong value for dir");
// Generate a .onion address // Generate a .onion address
$torConf = file_get_contents(TOR_CONFIG_PATH); $torConf = file_get_contents(TOR_CONFIG_PATH);
$torConf = $torConf . "\nHiddenServiceDir " . TOR_KEYS_PATH . "/" . $_POST['dir'] . "/\nHiddenServicePort 80 [::1]:80"; $torConf = $torConf . "\nHiddenServiceDir " . TOR_KEYS_PATH . "/" . $_POST['dir'] . "/\nHiddenServicePort 80 [::1]:80";
file_put_contents(TOR_CONFIG_PATH, $torConf); file_put_contents(TOR_CONFIG_PATH, $torConf);
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-tor", $output); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-tor", $output);
addNiverLog("Tor reloaded by " . $_SESSION['username'], $output); addNiverLog("Tor reloaded by " . $_SESSION['username'], $output);
// Copy generated address to a location readable by PHP // Copy generated address to a location readable by PHP
exec(SUDO_PATH . " " . MANIVER_PATH . " export-tor " . $_SESSION['username'] . " " . $_POST['dir'], $output); exec(SUDO_PATH . " " . MANIVER_PATH . " export-tor " . $_SESSION['username'] . " " . $_POST['dir'], $output);
addNiverLog("Tor data exported by " . $_SESSION['username'], $output); addNiverLog("Tor data exported by " . $_SESSION['username'], $output);
// Wait // Wait
sleep(1); sleep(1);
// Get the address generated by Tor // Get the address generated by Tor
$onion = file_get_contents(HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir'] . "/hostname"); $onion = file_get_contents(HT_PATH . "/" . $_SESSION['username'] . "/ht/" . $_POST['dir'] . "/hostname");
$onion = str_replace(array("\r", "\n"), "", $onion); $onion = str_replace(array("\r", "\n"), "", $onion);
// Store it in the database // Store it in the database
addSite($_SESSION['username'], $_POST['dir'], $onion, "onion", "http"); addSite($_SESSION['username'], $_POST['dir'], $onion, "onion", "http");
// Add it to Nginx // Add it to Nginx
$nginxConf = file_get_contents(NIVER_TEMPLATE_PATH . "/nginx/onion.template"); $nginxConf = file_get_contents(NIVER_TEMPLATE_PATH . "/nginx/onion.template");
$nginxConf = preg_replace("#DOMAIN#", $onion, $nginxConf); $nginxConf = preg_replace("#DOMAIN#", $onion, $nginxConf);
$nginxConf = preg_replace("#DIR#", $_POST['dir'], $nginxConf); $nginxConf = preg_replace("#DIR#", $_POST['dir'], $nginxConf);
$nginxConf = preg_replace("#USER#", $_SESSION['username'], $nginxConf); $nginxConf = preg_replace("#USER#", $_SESSION['username'], $nginxConf);
file_put_contents(NGINX_CONFIG_PATH . "/" . $_POST['dir'] . ".conf", $nginxConf); file_put_contents(NGINX_CONFIG_PATH . "/" . $_POST['dir'] . ".conf", $nginxConf);
// Reload Nginx // Reload Nginx
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-nginx", $output); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-nginx", $output);
addNiverLog("Nginx reloaded by " . $_SESSION['username'], $output); addNiverLog("Nginx reloaded by " . $_SESSION['username'], $output);
// Tell the user their site address // Tell the user their site address
echo "<p>L'adresse de votre site Onion HTTP est :<br><a href='http://" . $onion . "'<code>http://" . $onion . "</code></a></p>"; echo "<p>L'adresse de votre site Onion HTTP est :<br><a href='http://" . $onion . "'<code>http://" . $onion . "</code></a></p>";
} }

View File

@ -1,80 +1,80 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Ajouter un domaine sur un dossier de site<br> Ajouter un domaine sur un dossier de site<br>
Le domaine doit pointer vers ces adresses IP : Le domaine doit pointer vers ces adresses IP :
<br>IPv4 : <code><?= IPV4_ADDRESS ?></code> <br>IPv4 : <code><?= IPV4_ADDRESS ?></code>
<br>IPv6 : <code><?= IPV6_ADDRESS ?></code> <br>IPv6 : <code><?= IPV6_ADDRESS ?></code>
</p> </p>
<form method="post"> <form method="post">
<label for="domain">Domaine sur lequel répondre</label><br> <label for="domain">Domaine sur lequel répondre</label><br>
<input required="" placeholder="site.<?= DOMAIN_EXAMPLE ?>" id="domain" name="domain" type="text"><br> <input required="" placeholder="site.<?= DOMAIN_EXAMPLE ?>" id="domain" name="domain" type="text"><br>
<label for="dir">Dossier ciblé</label><br> <label for="dir">Dossier ciblé</label><br>
<select required="" name="dir" id="dir"> <select required="" name="dir" id="dir">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$fsDirs = listFsDirs($_SESSION['username']); $fsDirs = listFsDirs($_SESSION['username']);
$dbUsedDirs = listDbDirs($_SESSION['username'], "dns", "http"); $dbUsedDirs = listDbDirs($_SESSION['username'], "dns", "http");
$i = 0; $i = 0;
$j = 0; $j = 0;
$alreadyEnabledDirs = NULL; $alreadyEnabledDirs = NULL;
$notYetEnabledDirs = NULL; $notYetEnabledDirs = NULL;
if ($fsDirs) { if ($fsDirs) {
foreach ($fsDirs as $fsDir) { foreach ($fsDirs as $fsDir) {
if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) { if ($dbUsedDirs AND in_array($fsDir, $dbUsedDirs)) {
$alreadyEnabledDirs[$i] = $fsDir; $alreadyEnabledDirs[$i] = $fsDir;
$i++; $i++;
} else { } else {
$notYetEnabledDirs[$j] = $fsDir; $notYetEnabledDirs[$j] = $fsDir;
$j++; $j++;
} }
} }
if (!is_null($notYetEnabledDirs)) { if (!is_null($notYetEnabledDirs)) {
foreach ($notYetEnabledDirs as $dir) { foreach ($notYetEnabledDirs as $dir) {
echo "<option value='" . $dir . "'>" . $dir . "</option>"; echo "<option value='" . $dir . "'>" . $dir . "</option>";
} }
} }
if (!is_null($alreadyEnabledDirs)) { if (!is_null($alreadyEnabledDirs)) {
foreach ($alreadyEnabledDirs as $dir) { foreach ($alreadyEnabledDirs as $dir) {
echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>"; echo "<option disabled='' value='" . $dir . "'>" . $dir . "</option>";
} }
} }
} }
?> ?>
</select> </select>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['domain']) AND isset($_POST['dir']) AND isset($_SESSION['username'])) { if (isset($_POST['domain']) AND isset($_POST['dir']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
checkDomainFormat($_POST['domain']); checkDomainFormat($_POST['domain']);
if (!in_array($_POST['dir'], $notYetEnabledDirs)) if (!in_array($_POST['dir'], $notYetEnabledDirs))
exit("ERROR : Wrong value for dir"); exit("ERROR : Wrong value for dir");
addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "http"); addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "http");
$conf = file_get_contents(NIVER_TEMPLATE_PATH . "/nginx/dns.template"); $conf = file_get_contents(NIVER_TEMPLATE_PATH . "/nginx/dns.template");
$conf = preg_replace("#DOMAIN#", $_POST['domain'], $conf); $conf = preg_replace("#DOMAIN#", $_POST['domain'], $conf);
$conf = preg_replace("#DIR#", $_POST['dir'], $conf); $conf = preg_replace("#DIR#", $_POST['dir'], $conf);
$conf = preg_replace("#USER#", $_SESSION['username'], $conf); $conf = preg_replace("#USER#", $_SESSION['username'], $conf);
file_put_contents(NGINX_CONFIG_PATH . "/" . $_POST['domain'] . ".conf", $conf); file_put_contents(NGINX_CONFIG_PATH . "/" . $_POST['domain'] . ".conf", $conf);
// Reload Nginx // Reload Nginx
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-nginx"); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-nginx");
echo "Accès HTTP par domaine ajouté sur ce dossier !"; echo "Accès HTTP par domaine ajouté sur ce dossier !";
} }
?> ?>

View File

@ -1,30 +1,30 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<dl> <dl>
<dt><a class="htButton" href="sftp">Gérer l'accès SFTP</a></dt> <dt><a class="htButton" href="sftp">Gérer l'accès SFTP</a></dt>
<dd> <dd>
Accéder à son espace SFTP, pour publier et mettre à jour ses sites Accéder à son espace SFTP, pour publier et mettre à jour ses sites
</dd> </dd>
<dt><a class="htButton" href="http-onion">Accès HTTP en Onion</a></dt> <dt><a class="htButton" href="http-onion">Accès HTTP en Onion</a></dt>
<dd> <dd>
Un site HTML, accessible par Tor, avec une adresse en .onion Un site HTML, accessible par Tor, avec une adresse en .onion
</dd> </dd>
<dt><a class="htButton" href="https-domain">Accès HTTPS par DNS</a></dt> <dt><a class="htButton" href="https-domain">Accès HTTPS par DNS</a></dt>
<dd> <dd>
Un site HTML, accessible directement, par un nom de domaine Un site HTML, accessible directement, par un nom de domaine
</dd> </dd>
<dt><a class="htButton" href="gemini-onion">Accès Gemini en Onion</a></dt> <dt><a class="htButton" href="gemini-onion">Accès Gemini en Onion</a></dt>
<dd> <dd>
Une capsule Gemini, accessible par Tor, avec une adresse en .onion Une capsule Gemini, accessible par Tor, avec une adresse en .onion
</dd> </dd>
<dt><a class="htButton" href="gemini-domain">Accès Gemini par DNS</a></dt> <dt><a class="htButton" href="gemini-domain">Accès Gemini par DNS</a></dt>
<dd> <dd>
Une capsule Gemini, accessible directement, par un nom de domaine Une capsule Gemini, accessible directement, par un nom de domaine
</dd> </dd>
<dt><a class="htButton" href="le">Let's Encrypt</a></dt> <dt><a class="htButton" href="le">Let's Encrypt</a></dt>
<dd> <dd>
Installer un certificat Let's Encrypt sur un domaine Installer un certificat Let's Encrypt sur un domaine
</dd> </dd>
</dl> </dl>
<?php require "../bottom.inc.php"; ?> <?php require "../bottom.inc.php"; ?>

View File

@ -1,53 +1,53 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Installer un certificat Let's Encrypt Installer un certificat Let's Encrypt
</p> </p>
<form method="post"> <form method="post">
<label for="domain">Domaine ciblé</label><br> <label for="domain">Domaine ciblé</label><br>
<select required="" name="domain"> <select required="" name="domain">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$sites = selectSites($_SESSION['username'], "dns", "http", false); $sites = selectSites($_SESSION['username'], "dns", "http", false);
$leAvailable = selectSites($_SESSION['username'], "dns", "http", true); $leAvailable = selectSites($_SESSION['username'], "dns", "http", true);
foreach ($sites as $site) { ?> foreach ($sites as $site) { ?>
<option value="<?= $site['domain'] ?>"><?= $site['domain'] . " (/ht/" . $site['siteDir'] . ")" ?></option> <option value="<?= $site['domain'] ?>"><?= $site['domain'] . " (/ht/" . $site['siteDir'] . ")" ?></option>
<?php } ?> <?php } ?>
</select> </select>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['domain']) AND isset($_SESSION['username'])) { if (isset($_POST['domain']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
// Use maniver to use Certbot // Use maniver to use Certbot
exec(SUDO_PATH . " " . MANIVER_PATH . " le-install " . $_POST['domain'], $output, $returnCode); exec(SUDO_PATH . " " . MANIVER_PATH . " le-install " . $_POST['domain'], $output, $returnCode);
// Log Certbot response // Log Certbot response
addNiverLog($_SESSION['username'] . " installed a Let's Encrypt certificate on their site", $output, $returnCode); addNiverLog($_SESSION['username'] . " installed a Let's Encrypt certificate on their site", $output, $returnCode);
// Abort if Certbot failed // Abort if Certbot failed
if ($returnCode !== 0) if ($returnCode !== 0)
exit("Let's Encrypt certificate obtention failed. Try again later, or contact an administrator."); exit("Let's Encrypt certificate obtention failed. Try again later, or contact an administrator.");
// Replace self-signed certificate by Let's Encrypt certificate in Nginx configuration // Replace self-signed certificate by Let's Encrypt certificate in Nginx configuration
$conf = file_get_contents(NGINX_CONFIG_PATH . "/" . $_POST['domain'] . ".conf"); $conf = file_get_contents(NGINX_CONFIG_PATH . "/" . $_POST['domain'] . ".conf");
$conf = preg_replace("#/etc/ssl/certs/niver\.crt#", "/etc/letsencrypt/live/" . $_POST['domain'] . "/fullchain.pem", $conf); $conf = preg_replace("#/etc/ssl/certs/niver\.crt#", "/etc/letsencrypt/live/" . $_POST['domain'] . "/fullchain.pem", $conf);
$conf = preg_replace("#/etc/ssl/private/niver\.key#", "/etc/letsencrypt/live/" . $_POST['domain'] . "/privkey.pem", $conf); $conf = preg_replace("#/etc/ssl/private/niver\.key#", "/etc/letsencrypt/live/" . $_POST['domain'] . "/privkey.pem", $conf);
file_put_contents(NGINX_CONFIG_PATH . "/" . $_POST['domain'] . ".conf", $conf); file_put_contents(NGINX_CONFIG_PATH . "/" . $_POST['domain'] . ".conf", $conf);
// Reload Nginx // Reload Nginx
exec(SUDO_PATH . " " . MANIVER_PATH . " reload-nginx", $output, $returnCode); exec(SUDO_PATH . " " . MANIVER_PATH . " reload-nginx", $output, $returnCode);
// Abort if Maniver failed to reload Nginx // Abort if Maniver failed to reload Nginx
if ($returnCode !== 0) if ($returnCode !== 0)
exit("Nginx configuration reload failed. Try again later, or contact an administrator."); exit("Nginx configuration reload failed. Try again later, or contact an administrator.");
echo "Succès : La connexion avec votre site utilise désomais un certificat TLS émis par Let's Encrypt."; echo "Succès : La connexion avec votre site utilise désomais un certificat TLS émis par Let's Encrypt.";
} }
?> ?>

View File

@ -3,166 +3,166 @@
<?php <?php
if ($_SESSION['sftp_enabled'] == false) { ?> if ($_SESSION['sftp_enabled'] == false) { ?>
<p> <p>
Pour que vous puissiez mettre en ligne votre site via <abbr title="SSH File Transfert Protocol">SFTP</abbr>, veuillez définir un mot de passe. Pour que vous puissiez mettre en ligne votre site via <abbr title="SSH File Transfert Protocol">SFTP</abbr>, veuillez définir un mot de passe.
<br>Il sera loggué en clair dans le système et il ne pourra pas être modifié. <br>Il sera loggué en clair dans le système et il ne pourra pas être modifié.
</p> </p>
<form method="post"> <form method="post">
<label for="password">Créer le mot de passe</label><br> <label for="password">Créer le mot de passe</label><br>
<input required="" placeholder="**********" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]{8,}|.{10,1024}$" id="password" name="password" type="password"><br> <input required="" placeholder="**********" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])[a-zA-Z0-9]{8,}|.{10,1024}$" id="password" name="password" type="password"><br>
<input value="Activer" type="submit"> <input value="Activer" type="submit">
</form> </form>
<?php <?php
if (isset($_SESSION['username']) AND isset($_POST['password'])) { if (isset($_SESSION['username']) AND isset($_POST['password'])) {
antiCSRF(); antiCSRF();
// Setup SFTP access // Setup SFTP access
exec(SUDO_PATH . " " . MANIVER_PATH . " setup-user " . $_SESSION['username'] . " " . $_POST['password'], $output); exec(SUDO_PATH . " " . MANIVER_PATH . " setup-user " . $_SESSION['username'] . " " . $_POST['password'], $output);
addNiverLog($_SESSION['username'] . " enabled SFTP on their account", $output); addNiverLog($_SESSION['username'] . " enabled SFTP on their account", $output);
enableSftp($_SESSION['username']); enableSftp($_SESSION['username']);
$_SESSION['sftp_enabled'] = true; $_SESSION['sftp_enabled'] = true;
header('Location: ' . PREFIX . '/' . SERVICE . '/' . PAGE . '', true, 302); header('Location: ' . PREFIX . '/' . SERVICE . '/' . PAGE . '', true, 302);
exit(); exit();
} }
} else if ($_SESSION['sftp_enabled'] == true) { ?> } else if ($_SESSION['sftp_enabled'] == true) { ?>
Vous avez désormais accès à un espace <abbr title="SSH File Transfert Protocol">SFTP</abbr>. Vous pouvez téléverser vos sites dans <code>/ht/&lt;nom du site&gt;/*</code>. Vous avez désormais accès à un espace <abbr title="SSH File Transfert Protocol">SFTP</abbr>. Vous pouvez téléverser vos sites dans <code>/ht/&lt;nom du site&gt;/*</code>.
<br> <br>
<section> <section>
<h2>Quota</h2> <h2>Quota</h2>
L'espace est limité au total à 10Kio de stockage et 10 fichiers/dossiers. L'espace est limité au total à 10Kio de stockage et 10 fichiers/dossiers.
</section> </section>
<section> <section>
<h2>Clients SFTP</h2> <h2>Clients SFTP</h2>
<strong>Dolphin</strong> et <strong>GNOME Fichiers</strong> (<em>Nautilus</em>) sont disponibles sur la plupart des distributions GNU et sont installés par défaut respectivement sur les environnements de bureau KDE et GNOME. <a href="https://filezilla-project.org/"><strong>FileZilla</strong></a> est disponible aussi pour les autres systèmes d'exploitation de bureau. <strong>Dolphin</strong> et <strong>GNOME Fichiers</strong> (<em>Nautilus</em>) sont disponibles sur la plupart des distributions GNU et sont installés par défaut respectivement sur les environnements de bureau KDE et GNOME. <a href="https://filezilla-project.org/"><strong>FileZilla</strong></a> est disponible aussi pour les autres systèmes d'exploitation de bureau.
<br> <br>
C'est aussi possible d'utiliser le client <code>sftp</code> en ligne de commande. C'est aussi possible d'utiliser le client <code>sftp</code> en ligne de commande.
</section> </section>
<section> <section>
<h2>Informations de connexion</h2> <h2>Informations de connexion</h2>
<div> <div>
<a href="sftp://<?= $_SESSION['username'] ?>@sftp.niver.4.niv.re/">sftp://<?= $_SESSION['username'] ?>@sftp.niver.4.niv.re/</a> <a href="sftp://<?= $_SESSION['username'] ?>@sftp.niver.4.niv.re/">sftp://<?= $_SESSION['username'] ?>@sftp.niver.4.niv.re/</a>
</div> </div>
Indiquez les données ci-dessous à votre client <abbr title="SSH File Transfert Protocol">SFTP</abbr> pour y accéder. Indiquez les données ci-dessous à votre client <abbr title="SSH File Transfert Protocol">SFTP</abbr> pour y accéder.
<dl> <dl>
<dt>Utilisataire</dt> <dt>Utilisataire</dt>
<dd> <dd>
<code><?= $_SESSION['username'] ?></code> <code><?= $_SESSION['username'] ?></code>
</dd> </dd>
<dt>Clé de passe</dt> <dt>Clé de passe</dt>
<dd> <dd>
celle que vous avez définit lors de l'activation de l'accès <abbr title="SSH File Transfert Protocol">SFTP</abbr> celle que vous avez définit lors de l'activation de l'accès <abbr title="SSH File Transfert Protocol">SFTP</abbr>
</dd> </dd>
<dt>Serveur</dt> <dt>Serveur</dt>
<dd> <dd>
<code>sftp.niver.4.niv.re</code> <code>sftp.niver.4.niv.re</code>
</dd> </dd>
<dt>Port</dt> <dt>Port</dt>
<dd> <dd>
<code>22</code> (par défaut) <code>22</code> (par défaut)
</dd> </dd>
<dt>Dossier</dt> <dt>Dossier</dt>
<dd> <dd>
<code>/</code> <code>/</code>
</dd> </dd>
</dl> </dl>
</section> </section>
<section> <section>
<h2>Vérifier la connexion</h2> <h2>Vérifier la connexion</h2>
<section> <section>
<h3>Ed25519</h3> <h3>Ed25519</h3>
<ul> <ul>
<li> <li>
<code class="breakable"> <code class="breakable">
SHA256:k5gzcFr5BbOhNUgS6Nbyy15dXPpw6pmTo8OLZ5mLRmA SHA256:k5gzcFr5BbOhNUgS6Nbyy15dXPpw6pmTo8OLZ5mLRmA
</code> </code>
</li> </li>
<li> <li>
<code class="breakable"> <code class="breakable">
AAAAC3NzaC1lZDI1NTE5AAAAIF3RT3r6bYGw88TQ190PIZz1UUVV3Xt5SLOo39G+ShjR AAAAC3NzaC1lZDI1NTE5AAAAIF3RT3r6bYGw88TQ190PIZz1UUVV3Xt5SLOo39G+ShjR
</code> </code>
</li> </li>
<li> <li>
<details> <details>
<summary>Image ASCII</summary> <summary>Image ASCII</summary>
<samp> <samp>
<pre> <pre>
+--[ED25519 256]--+ +--[ED25519 256]--+
| .oo..* | | .oo..* |
| . ..+ * | | . ..+ * |
| . .. = . . . | | . .. = . . . |
| + E= + + o | | + E= + + o |
| . +..= S = . | | . +..= S = . |
| . .+ o = | | . .+ o = |
| . o...o... | | . o...o... |
| o..oB.+o | | o..oB.+o |
| ...oo+=+o | | ...oo+=+o |
+----[SHA256]-----+ +----[SHA256]-----+
</pre> </pre>
</samp> </samp>
</details> </details>
</li> </li>
</ul> </ul>
</section> </section>
<section> <section>
<h3>RSA 3072 bits</h3> <h3>RSA 3072 bits</h3>
<ul> <ul>
<li> <li>
<code class="breakable"> <code class="breakable">
SHA256:yu9PGTGpeCyjaDDG0RiInsMIa1w6t2c6Gv6oemzeFN4 SHA256:yu9PGTGpeCyjaDDG0RiInsMIa1w6t2c6Gv6oemzeFN4
</code> </code>
</li> </li>
<li> <li>
<details> <details>
<summary>Clé publique</summary> <summary>Clé publique</summary>
<code class="breakable"> <code class="breakable">
AAAAB3NzaC1yc2EAAAADAQABAAABgQC5Zj5nghhFpdFsyxS6LZd+cYejGR82kow2UsnoRtQ20SU6ro36f4HnFkRcJyY4uPeTyUECX9uBircpKsizfkdfzJf3sTtjrAwghVVdH8EXsK1UjWTt4rRaav3F+g86DEcx7mqMva6zpnoxONjzA+Inm3SD89VuvSl1ZmZBBEEsqsIifNPYVPG1LQg62OEY1gpe89w92CXeEM7rGarp04ux76ORxN93BwnH27q9yjyBensZ/AjL6OmTtDHD8wWG0G6E3gqsyVUiELysyvwW4z3bfSOLRTwtwFaHe7WRjf9iy53h+ZcYZeA+Xe1eTffj0JGtNX2Fh6DWgso1yOeVV0Nziw4wI3Cpr2iO1x4oxeT8qwgklYMuJTAlNaahLXmENtmeq7BkaDKVZb/IW+uLj517c7WnOEUtr1xUcw4yuXXFVRBspmHzkwEvHsix/ZNmofkqo7ZZv5MIoRW1ad6peb8ApkxZ8UNVGcxmJgZmOrW1GBlCpyJdwwSMrLfQH5Zw8dk= AAAAB3NzaC1yc2EAAAADAQABAAABgQC5Zj5nghhFpdFsyxS6LZd+cYejGR82kow2UsnoRtQ20SU6ro36f4HnFkRcJyY4uPeTyUECX9uBircpKsizfkdfzJf3sTtjrAwghVVdH8EXsK1UjWTt4rRaav3F+g86DEcx7mqMva6zpnoxONjzA+Inm3SD89VuvSl1ZmZBBEEsqsIifNPYVPG1LQg62OEY1gpe89w92CXeEM7rGarp04ux76ORxN93BwnH27q9yjyBensZ/AjL6OmTtDHD8wWG0G6E3gqsyVUiELysyvwW4z3bfSOLRTwtwFaHe7WRjf9iy53h+ZcYZeA+Xe1eTffj0JGtNX2Fh6DWgso1yOeVV0Nziw4wI3Cpr2iO1x4oxeT8qwgklYMuJTAlNaahLXmENtmeq7BkaDKVZb/IW+uLj517c7WnOEUtr1xUcw4yuXXFVRBspmHzkwEvHsix/ZNmofkqo7ZZv5MIoRW1ad6peb8ApkxZ8UNVGcxmJgZmOrW1GBlCpyJdwwSMrLfQH5Zw8dk=
</code> </code>
</details> </details>
</li> </li>
<li> <li>
<details> <details>
<summary>Image ASCII</summary> <summary>Image ASCII</summary>
<samp> <samp>
<pre> <pre>
+---[RSA 3072]----+ +---[RSA 3072]----+
|o. | |o. |
|+ +. . | |+ +. . |
|*++. + | |*++. + |
|+X.. o . o | |+X.. o . o |
|+o+ o + S . | |+o+ o + S . |
|.o + B = o | |.o + B = o |
| oo B E o | | oo B E o |
|..*= . . | |..*= . . |
|=B+.o .o.. | |=B+.o .o.. |
+----[SHA256]-----+ +----[SHA256]-----+
</pre> </pre>
</samp> </samp>
</details> </details>
</li> </li>
</ul> </ul>
</section> </section>
N'acceptez la connexion que si votre client vous montre l'une de ces signatures ! N'acceptez la connexion que si votre client vous montre l'une de ces signatures !
</section> </section>
<br> <br>
<?php <?php
} else { } else {
exit("Wrong value for sftp_enabled"); exit("Wrong value for sftp_enabled");
} }
?> ?>

View File

@ -1,49 +1,49 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
function addNiverLog($message, $outputLines, $returnCode = false) { function addNiverLog($message, $outputLines, $returnCode = false) {
$logs = "\n" . date("Y-m-d H:i:s") . " " . $message . "\n"; $logs = "\n" . date("Y-m-d H:i:s") . " " . $message . "\n";
if ($returnCode !== false) if ($returnCode !== false)
$logs = $logs . "Return code: " . $returnCode . "\n"; $logs = $logs . "Return code: " . $returnCode . "\n";
else else
$logs = $logs . "No return code logged\n"; $logs = $logs . "No return code logged\n";
foreach ($outputLines as $outputLine) { foreach ($outputLines as $outputLine) {
$logs = $logs . " " . $outputLine . "\n"; $logs = $logs . " " . $outputLine . "\n";
} }
file_put_contents(ROOT_PATH . "/niver.log", $logs, FILE_APPEND); file_put_contents(ROOT_PATH . "/niver.log", $logs, FILE_APPEND);
} }
function appendLog($log) { function appendLog($log) {
file_put_contents(ROOT_PATH . "/niver.log", date("Y-m-d H:i:s") . var_dump($log) . "\n", FILE_APPEND); file_put_contents(ROOT_PATH . "/niver.log", date("Y-m-d H:i:s") . var_dump($log) . "\n", FILE_APPEND);
} }
function checkAction($action) { function checkAction($action) {
if ($action === "delete") if ($action === "delete")
return "un"; return "un";
else if ($action === "add") else if ($action === "add")
return ""; return "";
else else
exit("ERROR: wrong value for action"); exit("ERROR: wrong value for action");
} }
function userExist($username) { function userExist($username) {
$usernameArray[0] = $username; $usernameArray[0] = $username;
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$op = $db->prepare('SELECT username FROM users WHERE username = ?'); $op = $db->prepare('SELECT username FROM users WHERE username = ?');
$op->execute($usernameArray); $op->execute($usernameArray);
$data = $op->fetch(); $data = $op->fetch();
if (isset($data['username'])) if (isset($data['username']))
$dbUsername = $data['username']; $dbUsername = $data['username'];
else else
$dbUsername = NULL; $dbUsername = NULL;
if (isset($dbUsername)) { if (isset($dbUsername)) {
return true; return true;
} else { } else {
return false; return false;
} }
} }

View File

@ -1,59 +1,59 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
function hashPassword($password) { function hashPassword($password) {
return password_hash($password, ALGO_PASSWORD, OPTIONS_PASSWORD); return password_hash($password, ALGO_PASSWORD, OPTIONS_PASSWORD);
} }
function checkPassword($username, $password) { function checkPassword($username, $password) {
$username2[0] = $username; $username2[0] = $username;
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$op = $db->prepare('SELECT username, password FROM users WHERE username = ?'); $op = $db->prepare('SELECT username, password FROM users WHERE username = ?');
$op->execute($username2); $op->execute($username2);
$dbPassword = $op->fetch()['password']; $dbPassword = $op->fetch()['password'];
return password_verify($password, $dbPassword); return password_verify($password, $dbPassword);
} }
function outdatedPasswordHash($username) { function outdatedPasswordHash($username) {
$username2[0] = $username; $username2[0] = $username;
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$op = $db->prepare('SELECT username, password FROM users WHERE username = ?'); $op = $db->prepare('SELECT username, password FROM users WHERE username = ?');
$op->execute($username2); $op->execute($username2);
$dbPassword = $op->fetch()['password']; $dbPassword = $op->fetch()['password'];
return password_needs_rehash($dbPassword, ALGO_PASSWORD, OPTIONS_PASSWORD); return password_needs_rehash($dbPassword, ALGO_PASSWORD, OPTIONS_PASSWORD);
} }
function changePassword($username, $password) { function changePassword($username, $password) {
$password = hashPassword($password); $password = hashPassword($password);
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$stmt = $db->prepare("UPDATE users SET password = :password WHERE username = :username"); $stmt = $db->prepare("UPDATE users SET password = :password WHERE username = :username");
$stmt->bindParam(':username', $username); $stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password); $stmt->bindParam(':password', $password);
$stmt->execute(); $stmt->execute();
} }
function antiCSRF() { function antiCSRF() {
if (!isset($_SERVER['HTTP_SEC_FETCH_SITE']) AND !isset($_SERVER['HTTP_ORIGIN'])) if (!isset($_SERVER['HTTP_SEC_FETCH_SITE']) AND !isset($_SERVER['HTTP_ORIGIN']))
exit("ERROR: Browser sent neither Sec-Fetch-Site nor Origin HTTP headers, so anti-CSRF verification can't be done."); exit("ERROR: Browser sent neither Sec-Fetch-Site nor Origin HTTP headers, so anti-CSRF verification can't be done.");
if (isset($_SERVER['HTTP_ORIGIN']) AND $_SERVER['HTTP_ORIGIN'] !== ORIGIN) if (isset($_SERVER['HTTP_ORIGIN']) AND $_SERVER['HTTP_ORIGIN'] !== ORIGIN)
exit("ERROR: Anti-CSRF verification failed"); exit("ERROR: Anti-CSRF verification failed");
if (isset($_SERVER['HTTP_SEC_FETCH_SITE']) AND $_SERVER['HTTP_SEC_FETCH_SITE'] !== "same-origin") if (isset($_SERVER['HTTP_SEC_FETCH_SITE']) AND $_SERVER['HTTP_SEC_FETCH_SITE'] !== "same-origin")
exit("ERROR: Anti-CSRF verification failed"); exit("ERROR: Anti-CSRF verification failed");
} }

View File

@ -1,6 +1,6 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
// --- Constants definitions --- // --- Constants definitions ---
@ -46,30 +46,30 @@ define("SUBDOMAIN_REGEX", "^[a-z]{4,63}$");
// Password storage security // Password storage security
define("ALGO_PASSWORD", PASSWORD_ARGON2ID); define("ALGO_PASSWORD", PASSWORD_ARGON2ID);
define("OPTIONS_PASSWORD", array( define("OPTIONS_PASSWORD", array(
"memory_cost" => 65536, "memory_cost" => 65536,
"time_cost" => 24, "time_cost" => 24,
"threads" => 64, "threads" => 64,
)); ));
// Color scheme // Color scheme
define("THEME", array( define("THEME", array(
// Displayed on light theme // Displayed on light theme
'darkRegColor' => "#D100D1", 'darkRegColor' => "#D100D1",
'darkNsColor' => "#006DFF", 'darkNsColor' => "#006DFF",
'darkHtColor' => "#008768", 'darkHtColor' => "#008768",
'darkAuthColor' => "#EE0000", 'darkAuthColor' => "#EE0000",
// Displayed on dark theme // Displayed on dark theme
'lightRegColor' => "#FF50FF", 'lightRegColor' => "#FF50FF",
'lightNsColor' => "#00FFFF", 'lightNsColor' => "#00FFFF",
'lightHtColor' => "#FFFF00", 'lightHtColor' => "#FFFF00",
'lightAuthColor' => "#00FF00", 'lightAuthColor' => "#00FF00",
'lightColor' => '#FFFFFF', 'lightColor' => '#FFFFFF',
'darkColor' => '#000000', 'darkColor' => '#000000',
)); ));
// Public suffixes // Public suffixes
define("SUFFIXES", array( define("SUFFIXES", array(
REGISTRY, REGISTRY,
)); ));

View File

@ -1,59 +1,59 @@
<label for="action">Action</label> <label for="action">Action</label>
<select name="action" id="action"> <select name="action" id="action">
<option value="add">Ajouter</option> <option value="add">Ajouter</option>
<option value="delete">Retirer</option> <option value="delete">Retirer</option>
</select> </select>
<br> <br>
<fieldset> <fieldset>
<legend>Domaine</legend> <legend>Domaine</legend>
<div> <div>
<label for="subdomain">Sous-domaine</label> <label for="subdomain">Sous-domaine</label>
<br> <br>
<input id="subdomain" size="16" placeholder="www" pattern="^(([a-z0-9_-]{1,63}\.?){1,127})|(@){1}$" name="subdomain" type="text"> <input id="subdomain" size="16" placeholder="www" pattern="^(([a-z0-9_-]{1,63}\.?){1,127})|(@){1}$" name="subdomain" type="text">
</div> </div>
<div> <div>
<label for="zone">Zone</label> <label for="zone">Zone</label>
<br> <br>
<select required="" name="zone" id="zone"> <select required="" name="zone" id="zone">
<option value="" disabled="" selected="">-</option> <option value="" disabled="" selected="">-</option>
<?php <?php
$zones = nsListUserZones($_SESSION['username']); $zones = nsListUserZones($_SESSION['username']);
if (!empty($zones)) { if (!empty($zones)) {
foreach ($zones as $zone) foreach ($zones as $zone)
echo "<option value='" . $zone . "'>" . $zone . "</option>"; echo "<option value='" . $zone . "'>" . $zone . "</option>";
} }
?> ?>
</select> </select>
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend><abbr title="Time To Live">TTL</abbr></legend> <legend><abbr title="Time To Live">TTL</abbr></legend>
<div> <div>
<label for="ttl-value">Valeur</label> <label for="ttl-value">Valeur</label>
<br> <br>
<input required="" id="ttl-value" list="ttls" name="ttl-value" size="6" type="number" min="1" max="432000" value="10800" placeholder="10800"> <input required="" id="ttl-value" list="ttls" name="ttl-value" size="6" type="number" min="1" max="432000" value="10800" placeholder="10800">
<datalist id="ttls"> <datalist id="ttls">
<option value="900"> <option value="900">
<option value="1800"> <option value="1800">
<option value="3600"> <option value="3600">
<option value="10800"> <option value="10800">
<option value="21600"> <option value="21600">
<option value="86400"> <option value="86400">
<option value="432000"> <option value="432000">
</datalist> </datalist>
</div> </div>
<div> <div>
<label for="ttl-multiplier">Unité</label> <label for="ttl-multiplier">Unité</label>
<br> <br>
<select required="" name="ttl-multiplier" id="ttl-multiplier"> <select required="" name="ttl-multiplier" id="ttl-multiplier">
<option value="1">seconde</option> <option value="1">seconde</option>
<option value="60">minute</option> <option value="60">minute</option>
<option value="3600">heure</option> <option value="3600">heure</option>
<option value="86400">jour</option> <option value="86400">jour</option>
</select> </select>
</div> </div>
</fieldset> </fieldset>

View File

@ -1,32 +1,32 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
function checkIpFormat($ip) { function checkIpFormat($ip) {
if (!filter_var($ip, FILTER_VALIDATE_IP)) if (!filter_var($ip, FILTER_VALIDATE_IP))
exit("ERROR: wrong IP address"); exit("ERROR: wrong IP address");
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE))
exit("ERROR: IP address is on the private range"); exit("ERROR: IP address is on the private range");
if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)) if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE))
exit("ERROR: IP address is on the reserved range"); exit("ERROR: IP address is on the reserved range");
} }
function checkAbsoluteDomainFormat($domain) { function checkAbsoluteDomainFormat($domain) {
// If the domain must end with a dot // 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)) if (!filter_var($domain, FILTER_VALIDATE_DOMAIN) OR !preg_match("/^([a-z0-9_-]{1,63}\.){2,127}$/", $domain))
exit("ERROR: wrong domain"); exit("ERROR: wrong domain");
} }
function checkDomainFormat($domain) { function checkDomainFormat($domain) {
// If the domain must end without a dot // 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)) 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"); exit("ERROR: wrong domain");
} }
function checkPasswordFormat($password) { function checkPasswordFormat($password) {
return preg_match("/" . PASSWORD_REGEX . "/", $password); return preg_match("/" . PASSWORD_REGEX . "/", $password);
} }
function checkUsernameFormat($username) { function checkUsernameFormat($username) {
return preg_match("/" . USERNAME_REGEX . "/", $username); return preg_match("/" . USERNAME_REGEX . "/", $username);
} }

View File

@ -1,126 +1,126 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
function listFsDirs($username) { function listFsDirs($username) {
exec(LS_PATH . " --format=single-column -d " . HT_PATH . "/" . $username . "/ht/*/", $absoluteDirs); exec(LS_PATH . " --format=single-column -d " . HT_PATH . "/" . $username . "/ht/*/", $absoluteDirs);
$relativeDirs = false; $relativeDirs = false;
foreach ($absoluteDirs as $i => $absoluteDir) { foreach ($absoluteDirs as $i => $absoluteDir) {
$tree = explode("/", $absoluteDir); // The last key is NULL $tree = explode("/", $absoluteDir); // The last key is NULL
end($tree); end($tree);
$relativeDirs[$i] = prev($tree); // The name of the site dir is the before last key $relativeDirs[$i] = prev($tree); // The name of the site dir is the before last key
} }
return $relativeDirs; return $relativeDirs;
} }
function addSite($username, $siteDir, $domain, $domainType, $protocol) { function addSite($username, $siteDir, $domain, $domainType, $protocol) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$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)"); $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"); $time = date("Y-m-d H:i:s");
if ($domainType === "dns" AND $protocol === "http") if ($domainType === "dns" AND $protocol === "http")
$le_enabled = 0; $le_enabled = 0;
else else
$le_enabled = NULL; $le_enabled = NULL;
$op->bindParam(':username', $username); $op->bindParam(':username', $username);
$op->bindParam(':site_dir', $siteDir); $op->bindParam(':site_dir', $siteDir);
$op->bindParam(':domain', $domain); $op->bindParam(':domain', $domain);
$op->bindParam(':domain_type', $domainType); $op->bindParam(':domain_type', $domainType);
$op->bindParam(':protocol', $protocol); $op->bindParam(':protocol', $protocol);
$op->bindParam(':creation_date', $time); $op->bindParam(':creation_date', $time);
$op->bindParam(':le_enabled', $le_enabled); $op->bindParam(':le_enabled', $le_enabled);
$op->execute(); $op->execute();
} }
function listDbDirs($username, $domainType, $protocol) { function listDbDirs($username, $domainType, $protocol) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$usernameArray[0] = $username; $usernameArray[0] = $username;
$op = $db->prepare('SELECT site_dir FROM sites WHERE username = :username AND domain_type = :domain_type AND protocol = :protocol'); $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(':username', $username);
$op->bindParam(':domain_type', $domainType); $op->bindParam(':domain_type', $domainType);
$op->bindParam(':protocol', $protocol); $op->bindParam(':protocol', $protocol);
$op->execute(); $op->execute();
$i = 0; $i = 0;
$data = $op->fetch(); $data = $op->fetch();
if (isset($data['site_dir'])) if (isset($data['site_dir']))
$siteDir = $data['site_dir']; $siteDir = $data['site_dir'];
else else
$siteDir = NULL; $siteDir = NULL;
while ($siteDir != NULL) { while ($siteDir != NULL) {
$siteDirs[$i] = $siteDir; $siteDirs[$i] = $siteDir;
$i++; $i++;
$data = $op->fetch(); $data = $op->fetch();
if (isset($data['site_dir'])) if (isset($data['site_dir']))
$siteDir = $data['site_dir']; $siteDir = $data['site_dir'];
else else
$siteDir = NULL; $siteDir = NULL;
} }
if (isset($siteDirs)) if (isset($siteDirs))
return $siteDirs; return $siteDirs;
else else
return false; return false;
} }
function sftpStatus($username) { function sftpStatus($username) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$usernameArr[0] = $username; $usernameArr[0] = $username;
$op = $db->prepare('SELECT sftp_enabled FROM users WHERE username = ?'); $op = $db->prepare('SELECT sftp_enabled FROM users WHERE username = ?');
$op->execute($usernameArr); $op->execute($usernameArr);
$status = $op->fetch()['sftp_enabled']; $status = $op->fetch()['sftp_enabled'];
if ($status == "0") { if ($status == "0") {
return false; return false;
} else if ($status == "1") { } else if ($status == "1") {
return true; return true;
} else { } else {
exit("Wrong value for sftp_enabled"); exit("Wrong value for sftp_enabled");
} }
} }
function enableSftp($username) { function enableSftp($username) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$op = $db->prepare("UPDATE users SET sftp_enabled = 1 WHERE username = :username"); $op = $db->prepare("UPDATE users SET sftp_enabled = 1 WHERE username = :username");
$op->bindParam(':username', $username); $op->bindParam(':username', $username);
$op->execute(); $op->execute();
} }
function selectSites($username, $domainType, $protocol, $onlyLeAvailable) { function selectSites($username, $domainType, $protocol, $onlyLeAvailable) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$usernameArray[0] = $username; $usernameArray[0] = $username;
$query = "SELECT site_dir,domain FROM sites WHERE username = :username AND domain_type = :domain_type AND protocol = :protocol"; $query = "SELECT site_dir,domain FROM sites WHERE username = :username AND domain_type = :domain_type AND protocol = :protocol";
if ($onlyLeAvailable === true) if ($onlyLeAvailable === true)
$query = $query . " AND le_enabled = 0"; $query = $query . " AND le_enabled = 0";
$op = $db->prepare($query); $op = $db->prepare($query);
$op->bindParam(':username', $username); $op->bindParam(':username', $username);
$op->bindParam(':domain_type', $domainType); $op->bindParam(':domain_type', $domainType);
$op->bindParam(':protocol', $protocol); $op->bindParam(':protocol', $protocol);
$op->execute(); $op->execute();
$i = 0; $i = 0;
$entry = $op->fetch(); $entry = $op->fetch();
while (isset($entry['site_dir'])) { while (isset($entry['site_dir'])) {
$result[$i]["siteDir"] = $entry['site_dir']; $result[$i]["siteDir"] = $entry['site_dir'];
$result[$i]["domain"] = $entry['domain']; $result[$i]["domain"] = $entry['domain'];
$i++; $i++;
$entry = $op->fetch(); $entry = $op->fetch();
} }
if (isset($result)) if (isset($result))
return $result; return $result;
else else
return false; return false;
} }

View File

@ -1,83 +1,83 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
function nsCommonRequirements() { function nsCommonRequirements() {
if (isset($_POST['action']) if (isset($_POST['action'])
AND isset($_POST['zone']) AND isset($_POST['zone'])
AND isset($_POST['ttl-value']) AND isset($_POST['ttl-value'])
AND isset($_POST['ttl-multiplier']) AND isset($_POST['ttl-multiplier'])
AND isset($_SESSION['username']) AND isset($_SESSION['username'])
) { ) {
antiCSRF(); antiCSRF();
return true; return true;
} }
} }
function nsParseCommonRequirements() { function nsParseCommonRequirements() {
$values['action'] = checkAction($_POST['action']); $values['action'] = checkAction($_POST['action']);
nsCheckZonePossession($_POST['zone']); nsCheckZonePossession($_POST['zone']);
if (($_POST['subdomain'] === "") OR ($_POST['subdomain'] === "@")) if (($_POST['subdomain'] === "") OR ($_POST['subdomain'] === "@"))
$values['domain'] = $_POST['zone']; $values['domain'] = $_POST['zone'];
else else
$values['domain'] = $_POST['subdomain'] . "." . $_POST['zone']; $values['domain'] = $_POST['subdomain'] . "." . $_POST['zone'];
checkAbsoluteDomainFormat($values['domain']); checkAbsoluteDomainFormat($values['domain']);
$values['ttl'] = $_POST['ttl-value'] * $_POST['ttl-multiplier']; $values['ttl'] = $_POST['ttl-value'] * $_POST['ttl-multiplier'];
if (!($values['ttl'] >= 300 AND $values['ttl'] <= 432000)) 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)"); exit("Erreur : le TTL doit être compris entre 5 minutes et 5 jours (entre 300 et 432000 secondes)");
return $values; return $values;
} }
function nsListUserZones($username) { function nsListUserZones($username) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$usernameArray[0] = $username; $usernameArray[0] = $username;
$op = $db->prepare('SELECT zone FROM zones WHERE username = ?'); $op = $db->prepare('SELECT zone FROM zones WHERE username = ?');
$op->execute($usernameArray); $op->execute($usernameArray);
$data = $op->fetch(); $data = $op->fetch();
if (isset($data['zone'])) if (isset($data['zone']))
$zone = $data['zone']; $zone = $data['zone'];
else else
$zone = NULL; $zone = NULL;
$i = 0; $i = 0;
$zones = NULL; $zones = NULL;
while ($zone != NULL) { while ($zone != NULL) {
$zones[$i] = $zone; $zones[$i] = $zone;
$i++; $i++;
$data = $op->fetch(); $data = $op->fetch();
if (isset($data['zone'])) if (isset($data['zone']))
$zone = $data['zone']; $zone = $data['zone'];
else else
$zone = NULL; $zone = NULL;
} }
return $zones; return $zones;
} }
function nsCheckZonePossession($submittedZone) { function nsCheckZonePossession($submittedZone) {
checkAbsoluteDomainFormat($submittedZone); checkAbsoluteDomainFormat($submittedZone);
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$username[0] = $_SESSION['username']; $username[0] = $_SESSION['username'];
$op = $db->prepare('SELECT zone FROM zones WHERE username = ?'); $op = $db->prepare('SELECT zone FROM zones WHERE username = ?');
$op->execute($username); $op->execute($username);
$dbZone = $op->fetch()['zone']; $dbZone = $op->fetch()['zone'];
while ($dbZone != NULL) { while ($dbZone != NULL) {
if ($dbZone === $submittedZone) return; if ($dbZone === $submittedZone) return;
$dbZone = $op->fetch()['zone']; $dbZone = $op->fetch()['zone'];
} }
// If there is no entry in the database for the user matching the submitted zone // 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"); exit("ERROR: You don't own this zone on the nameserver");
} }

View File

@ -1,117 +1,117 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
switch (SERVICE) { switch (SERVICE) {
case "ns": case "ns":
$page['service'] = "Serveurs de noms"; $page['service'] = "Serveurs de noms";
switch (PAGE) { switch (PAGE) {
case "index": case "index":
$page['title'] = $page['service']; $page['title'] = $page['service'];
break; break;
case "dnssec": case "dnssec":
$page['title'] = "Obtenir les enregistrements DS"; $page['title'] = "Obtenir les enregistrements DS";
break; break;
case "ip": case "ip":
$page['title'] = "Enregistrements A et AAAA"; $page['title'] = "Enregistrements A et AAAA";
break; break;
case "ns": case "ns":
$page['title'] = "Enregistrement NS"; $page['title'] = "Enregistrement NS";
break; break;
case "txt": case "txt":
$page['title'] = "Enregistrement TXT"; $page['title'] = "Enregistrement TXT";
break; break;
case "caa": case "caa":
$page['title'] = "Enregistrement CAA"; $page['title'] = "Enregistrement CAA";
break; break;
case "srv": case "srv":
$page['title'] = "Enregistrement SRV"; $page['title'] = "Enregistrement SRV";
break; break;
case "mx": case "mx":
$page['title'] = "Enregistrement MX"; $page['title'] = "Enregistrement MX";
break; break;
case "sshfp": case "sshfp":
$page['title'] = "Enregistrement SSHFP"; $page['title'] = "Enregistrement SSHFP";
break; break;
case "tlsa": case "tlsa":
$page['title'] = "Enregistrement TLSA"; $page['title'] = "Enregistrement TLSA";
break; break;
case "zone": case "zone":
$page['title'] = "Gérer ses zones"; $page['title'] = "Gérer ses zones";
break; break;
} }
break; break;
case "reg": case "reg":
$page['service'] = "Registre"; $page['service'] = "Registre";
switch (PAGE) { switch (PAGE) {
case "index": case "index":
$page['title'] = $page['service']; $page['title'] = $page['service'];
break; break;
case "ns": case "ns":
$page['title'] = "Ajouter un enregistrement NS"; $page['title'] = "Ajouter un enregistrement NS";
break; break;
case "register": case "register":
$page['title'] = "Enregistrer un nouveau domaine"; $page['title'] = "Enregistrer un nouveau domaine";
break; break;
case "glue": case "glue":
$page['title'] = "Créer un Glue Record"; $page['title'] = "Créer un Glue Record";
break; break;
case "ds": case "ds":
$page['title'] = "Ajouter un enregistrement DS"; $page['title'] = "Ajouter un enregistrement DS";
break; break;
} }
break; break;
case "auth": case "auth":
$page['service'] = "Authentification"; $page['service'] = "Authentification";
switch (PAGE) { switch (PAGE) {
case "index": case "index":
$page['title'] = $page['service']; $page['title'] = $page['service'];
break; break;
case "login": case "login":
$page['title'] = "Se connecter"; $page['title'] = "Se connecter";
break; break;
case "register": case "register":
$page['title'] = "Créer un compte"; $page['title'] = "Créer un compte";
break; break;
case "password": case "password":
$page['title'] = "Changer la clé de passe"; $page['title'] = "Changer la clé de passe";
break; break;
case "logout": case "logout":
$page['title'] = "Déconnexion"; $page['title'] = "Déconnexion";
break; break;
} }
break; break;
case "ht": case "ht":
$page['service'] = "Hypertexte"; $page['service'] = "Hypertexte";
switch (PAGE) { switch (PAGE) {
case "mkdir": case "mkdir":
$page['title'] = "Créer un dossier de site"; $page['title'] = "Créer un dossier de site";
break; break;
case "gemini-onion": case "gemini-onion":
$page['title'] = "Accès Gemini en Onion"; $page['title'] = "Accès Gemini en Onion";
break; break;
case "gemini-domain": case "gemini-domain":
$page['title'] = "Accès Gemini par domaine"; $page['title'] = "Accès Gemini par domaine";
break; break;
case "http-onion": case "http-onion":
$page['title'] = "Accès HTTP en Onion"; $page['title'] = "Accès HTTP en Onion";
break; break;
case "https-domain": case "https-domain":
$page['title'] = "Accès HTTPS par domaine"; $page['title'] = "Accès HTTPS par domaine";
break; break;
case "le": case "le":
$page['title'] = "Installer un certificat Let's Encrypt"; $page['title'] = "Installer un certificat Let's Encrypt";
break; break;
case "index": case "index":
$page['title'] = $page['service']; $page['title'] = $page['service'];
break; break;
case "sftp": case "sftp":
$page['title'] = "Gérer l'accès SFTP"; $page['title'] = "Gérer l'accès SFTP";
break; break;
} }
break; break;
} }

View File

@ -1,78 +1,78 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
function regGetUpperDomain($domain) { function regGetUpperDomain($domain) {
// Remove anything before the first dot and the first dot itself // Remove anything before the first dot and the first dot itself
return preg_replace("/^[^.]+\./", "", $domain); return preg_replace("/^[^.]+\./", "", $domain);
} }
function regListUserDomains($username) { function regListUserDomains($username) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$usernameArray[0] = $username; $usernameArray[0] = $username;
$op = $db->prepare('SELECT domain FROM registry WHERE username = ?'); $op = $db->prepare('SELECT domain FROM registry WHERE username = ?');
$op->execute($usernameArray); $op->execute($usernameArray);
$domains = false; $domains = false;
$i = 0; $i = 0;
$data = $op->fetch(); $data = $op->fetch();
$domain = $data['domain']; $domain = $data['domain'];
while ($domain != NULL) { while ($domain != NULL) {
$domains[$i] = $domain; $domains[$i] = $domain;
$data = $op->fetch(); $data = $op->fetch();
if (isset($data['domain'])) if (isset($data['domain']))
$domain = $data['domain']; $domain = $data['domain'];
else else
$domain = NULL; $domain = NULL;
$i++; $i++;
} }
return $domains; return $domains;
} }
function regCheckDomainPossession($domain) { function regCheckDomainPossession($domain) {
checkAbsoluteDomainFormat($domain); checkAbsoluteDomainFormat($domain);
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$username[0] = $_SESSION['username']; $username[0] = $_SESSION['username'];
$op = $db->prepare('SELECT domain FROM registry WHERE username = ?'); $op = $db->prepare('SELECT domain FROM registry WHERE username = ?');
$op->execute($username); $op->execute($username);
$dbDomain = $op->fetch()['domain']; $dbDomain = $op->fetch()['domain'];
$owned = false; $owned = false;
while ($dbDomain != NULL) { while ($dbDomain != NULL) {
if ($dbDomain === $domain) { if ($dbDomain === $domain) {
$owned = true; $owned = true;
break; break;
} }
$dbDomain = $op->fetch()['domain']; $dbDomain = $op->fetch()['domain'];
} }
if (!($owned === true)) if (!($owned === true))
exit("Erreur : Vous ne possédez pas ce domaine sur le registre !"); exit("Erreur : Vous ne possédez pas ce domaine sur le registre !");
} }
function regIsFree($domain) { function regIsFree($domain) {
$domainArray[0] = $domain; $domainArray[0] = $domain;
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$req = $db->prepare('SELECT domain FROM registry WHERE domain = ?'); $req = $db->prepare('SELECT domain FROM registry WHERE domain = ?');
$req->execute($domainArray); $req->execute($domainArray);
$data = $req->fetch(); $data = $req->fetch();
if (isset($data['domain'])) { if (isset($data['domain'])) {
return false; return false;
} else { } else {
return true; return true;
} }
} }

View File

@ -1,22 +1,22 @@
<?php require "top.inc.php"; ?> <?php require "top.inc.php"; ?>
<dl> <dl>
<dt><a class="regButton" href="reg/">Registre <code><?= REGISTRY ?></code></a></dt> <dt><a class="regButton" href="reg/">Registre <code><?= REGISTRY ?></code></a></dt>
<dd> <dd>
Demander l'attribution d'un sous-domaine de <code><?= REGISTRY ?></code> Demander l'attribution d'un sous-domaine de <code><?= REGISTRY ?></code>
</dd> </dd>
<dt><a class="nsButton" href="ns/">Serveurs de noms</a></dt> <dt><a class="nsButton" href="ns/">Serveurs de noms</a></dt>
<dd> <dd>
Utiliser le serveur de noms de Niver pour héberger ses zones Utiliser le serveur de noms de Niver pour héberger ses zones
</dd> </dd>
<dt><a class="htButton" href="ht/">Hypertexte</a></dt> <dt><a class="htButton" href="ht/">Hypertexte</a></dt>
<dd> <dd>
Mettre en ligne son site statique sur un espace <abbr title="SSH File Transfert Protocol">SFTP</abbr>, et le faire répondre en <abbr title="HyperText Transfert Protocol">HTTP</abbr> ou Gemini par le DNS ou Tor Mettre en ligne son site statique sur un espace <abbr title="SSH File Transfert Protocol">SFTP</abbr>, et le faire répondre en <abbr title="HyperText Transfert Protocol">HTTP</abbr> ou Gemini par le DNS ou Tor
</dd> </dd>
<dt><a class="authButton" href="auth/">Authentification</a></dt> <dt><a class="authButton" href="auth/">Authentification</a></dt>
<dd> <dd>
Gérer son compte Niver Gérer son compte Niver
</dd> </dd>
</dl> </dl>
<?php require "bottom.inc.php"; ?> <?php require "bottom.inc.php"; ?>

View File

@ -1,160 +1,160 @@
.button { .button {
font-size: 35px; font-size: 35px;
font-weight: 600; font-weight: 600;
border-width: 4px; border-width: 4px;
border-style: solid; border-style: solid;
text-decoration: none; text-decoration: none;
border-radius: 20px; border-radius: 20px;
padding: 14px 18px 16px 18px; padding: 14px 18px 16px 18px;
margin: 10px; margin: 10px;
margin-left: 0px; margin-left: 0px;
display: inline-block; display: inline-block;
} }
.htButton { .htButton {
.button(); .button();
@media @light { @media @light {
border-color: @darkHtColor; border-color: @darkHtColor;
color: @darkHtColor; color: @darkHtColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @darkHtColor; background-color: @darkHtColor;
&::selection { &::selection {
color: @darkHtColor; color: @darkHtColor;
} }
} }
&::selection { &::selection {
background-color: @darkHtColor; background-color: @darkHtColor;
} }
} }
@media @dark { @media @dark {
border-color: @lightHtColor; border-color: @lightHtColor;
color: @lightHtColor; color: @lightHtColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @lightHtColor; background-color: @lightHtColor;
&::selection { &::selection {
color: @lightHtColor; color: @lightHtColor;
} }
} }
&::selection { &::selection {
background-color: @lightHtColor; background-color: @lightHtColor;
} }
} }
} }
.regButton { .regButton {
.button(); .button();
@media @light { @media @light {
border-color: @darkRegColor; border-color: @darkRegColor;
color: @darkRegColor; color: @darkRegColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @darkRegColor; background-color: @darkRegColor;
&::selection { &::selection {
color: @darkRegColor; color: @darkRegColor;
} }
} }
&::selection { &::selection {
background-color: @darkRegColor; background-color: @darkRegColor;
} }
} }
@media @dark { @media @dark {
border-color: @lightRegColor; border-color: @lightRegColor;
color: @lightRegColor; color: @lightRegColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @lightRegColor; background-color: @lightRegColor;
&::selection { &::selection {
color: @lightRegColor; color: @lightRegColor;
} }
} }
&::selection { &::selection {
background-color: @lightRegColor; background-color: @lightRegColor;
} }
} }
} }
.nsButton { .nsButton {
.button(); .button();
@media @light { @media @light {
border-color: @darkNsColor; border-color: @darkNsColor;
color: @darkNsColor; color: @darkNsColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @darkNsColor; background-color: @darkNsColor;
&::selection { &::selection {
color: @darkNsColor; color: @darkNsColor;
} }
} }
&::selection { &::selection {
background-color: @darkNsColor; background-color: @darkNsColor;
} }
} }
@media @dark { @media @dark {
border-color: @lightNsColor; border-color: @lightNsColor;
color: @lightNsColor; color: @lightNsColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @lightNsColor; background-color: @lightNsColor;
&::selection { &::selection {
color: @lightNsColor; color: @lightNsColor;
} }
} }
&::selection { &::selection {
background-color: @lightNsColor; background-color: @lightNsColor;
} }
} }
} }
.authButton { .authButton {
.button(); .button();
@media @light { @media @light {
border-color: @darkAuthColor; border-color: @darkAuthColor;
color: @darkAuthColor; color: @darkAuthColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @darkAuthColor; background-color: @darkAuthColor;
&::selection { &::selection {
color: @darkAuthColor; color: @darkAuthColor;
} }
} }
&::selection { &::selection {
background-color: @darkAuthColor; background-color: @darkAuthColor;
} }
} }
@media @dark { @media @dark {
border-color: @lightAuthColor; border-color: @lightAuthColor;
color: @lightAuthColor; color: @lightAuthColor;
&:hover, &:focus { &:hover, &:focus {
background-color: @lightAuthColor; background-color: @lightAuthColor;
&::selection { &::selection {
color: @lightAuthColor; color: @lightAuthColor;
} }
} }
&::selection { &::selection {
background-color: @lightAuthColor; background-color: @lightAuthColor;
} }
} }
} }
@media @light { @media @light {
.htButton:hover, .regButton:hover, .nsButton:hover, .authButton:hover, .htButton:hover, .regButton:hover, .nsButton:hover, .authButton:hover,
.htButton:focus, .regButton:focus, .nsButton:focus, .authButton:focus { .htButton:focus, .regButton:focus, .nsButton:focus, .authButton:focus {
color: @lightColor; color: @lightColor;
&::selection { &::selection {
background-color: @lightColor; background-color: @lightColor;
} }
} }
} }
@media @dark { @media @dark {
.htButton:hover, .regButton:hover, .nsButton:hover, .authButton:hover, .htButton:hover, .regButton:hover, .nsButton:hover, .authButton:hover,
.htButton:focus, .regButton:focus, .nsButton:focus, .authButton:focus { .htButton:focus, .regButton:focus, .nsButton:focus, .authButton:focus {
color: @darkColor; color: @darkColor;
&::selection { &::selection {
background-color: @darkColor; background-color: @darkColor;
} }
} }
} }

View File

@ -1,103 +1,103 @@
form { form {
margin-left: 50px; margin-left: 50px;
margin-right: 50px; margin-right: 50px;
text-align: center; text-align: center;
@media (max-width: 500px) { @media (max-width: 500px) {
margin-left: 0px; margin-left: 0px;
margin-right: 0px; margin-right: 0px;
} }
} }
input, select { input, select {
border-radius: 12px; border-radius: 12px;
font-size: @fontSize; font-size: @fontSize;
margin: 5px; margin: 5px;
padding: 10px; padding: 10px;
border-style: solid; border-style: solid;
border-width: 2px; border-width: 2px;
&:hover { &:hover {
border-width: 3px; border-width: 3px;
padding: 9px; padding: 9px;
} }
&:focus { &:focus {
border-width: 4px; border-width: 4px;
padding: 8px; padding: 8px;
} }
@media @light { @media @light {
background-color: @lightColor; background-color: @lightColor;
color: @darkColor; color: @darkColor;
border-color: @darkColor; border-color: @darkColor;
} }
@media @dark { @media @dark {
background-color: @darkColor; background-color: @darkColor;
color: @lightColor; color: @lightColor;
border-color: @lightColor; border-color: @lightColor;
} }
} }
input[type=text] { input[type=text] {
font-family: monospace; font-family: monospace;
} }
input[type=submit] { input[type=submit] {
margin: 22px; margin: 22px;
} }
input#subdomain, input#ttl-value { input#subdomain, input#ttl-value {
text-align: right; text-align: right;
} }
#password { #password {
width: 32ch; width: 32ch;
text-align: center; text-align: center;
} }
#username { #username {
width: 16ch; width: 16ch;
} }
#keytag { #keytag {
width: 7ch; width: 7ch;
} }
input:invalid+span::after { input:invalid+span::after {
content: '✖'; content: '✖';
} }
input:valid+span::after { input:valid+span::after {
content: ''; // ✓ content: ''; // ✓
} }
input+span::after { input+span::after {
display: inline-block; display: inline-block;
width: 20px; width: 20px;
font-size: 30px; font-size: 30px;
padding-left: 20px; padding-left: 20px;
font-family: monospace; font-family: monospace;
} }
label.aboutInputCondition { label.aboutInputCondition {
display: block; display: block;
font-size: @fontSize - 10%; font-size: @fontSize - 10%;
} }
fieldset { fieldset {
border-radius: 20px; border-radius: 20px;
border-width: 2px; border-width: 2px;
border-style: solid; border-style: solid;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
@media @light { @media @light {
border-color: @darkColor; border-color: @darkColor;
} }
@media @dark { @media @dark {
border-color: @lightColor; border-color: @lightColor;
} }
} }

View File

@ -4,89 +4,89 @@
@dark: ~"(prefers-color-scheme: dark)"; @dark: ~"(prefers-color-scheme: dark)";
html { html {
margin: 0px; margin: 0px;
line-height: @fontSize + 6%; line-height: @fontSize + 6%;
} }
h1 { h1 {
font-size: @fontSize + 25px; font-size: @fontSize + 25px;
line-height: @fontSize + 30px line-height: @fontSize + 30px
} }
body { body {
margin: 0px; margin: 0px;
font-family: system-ui, sans-serif; font-family: system-ui, sans-serif;
font-size: @fontSize; font-size: @fontSize;
} }
header, main, footer { header, main, footer {
margin-left: 20%; margin-left: 20%;
margin-right: 20%; margin-right: 20%;
@media (max-width: 500px) { @media (max-width: 500px) {
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
} }
} }
code { code {
line-height: @fontSize + 6%; line-height: @fontSize + 6%;
font-size: @fontSize; font-size: @fontSize;
} }
nav { nav {
display: inline-block; display: inline-block;
margin-left: 20px; margin-left: 20px;
margin-right: 20px; margin-right: 20px;
} }
header { header {
text-align: center; text-align: center;
margin-top: 20px; margin-top: 20px;
} }
p { p {
margin: 0px; margin: 0px;
margin-bottom: 15px; margin-bottom: 15px;
} }
h2 { h2 {
margin: 0px; margin: 0px;
padding: 0px; padding: 0px;
} }
.breakable { .breakable {
word-break: break-all; word-break: break-all;
} }
@media @light { @media @light {
html { html {
background-color: @lightColor; background-color: @lightColor;
color: @darkColor; color: @darkColor;
} }
::selection { ::selection {
background-color: @darkColor; background-color: @darkColor;
color: @lightColor; color: @lightColor;
} }
a { a {
color: @darkColor; color: @darkColor;
} }
} }
@media @dark { @media @dark {
html { html {
background-color: @darkColor; background-color: @darkColor;
color: @lightColor; color: @lightColor;
} }
::selection { ::selection {
background-color: @lightColor; background-color: @lightColor;
color: @darkColor; color: @darkColor;
} }
a { a {
color: @lightColor; color: @lightColor;
} }
} }

View File

@ -2,47 +2,47 @@
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="flag">Flag</label> <label for="flag">Flag</label>
<br> <br>
<input id="flag" min="0" max="127" placeholder="0" name="flag" type="number"> <input id="flag" min="0" max="127" placeholder="0" name="flag" type="number">
<br> <br>
<label for="tag">Tag</label> <label for="tag">Tag</label>
<br> <br>
<input id="tag" minlenght="1" maxlength="128" pattern="^[a-z]{1,128}$" placeholder="issue" name="tag" type="text"> <input id="tag" minlenght="1" maxlength="128" pattern="^[a-z]{1,128}$" placeholder="issue" name="tag" type="text">
<br> <br>
<label for="value">Valeur</label> <label for="value">Valeur</label>
<br> <br>
<input id="value" minlenght="3" maxlength="1024" pattern="^[a-z0-9.-]{3,1024}$" placeholder="letsencrypt.org" name="value" type="text"> <input id="value" minlenght="3" maxlength="1024" pattern="^[a-z0-9.-]{3,1024}$" placeholder="letsencrypt.org" name="value" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['flag']) AND isset($_POST['flag'])
AND isset($_POST['tag']) AND isset($_POST['tag'])
AND isset($_POST['value']) AND isset($_POST['value'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!($_POST['flag'] >= 0 AND $_POST['flag'] <= 255)) if (!($_POST['flag'] >= 0 AND $_POST['flag'] <= 255))
exit("ERROR: Wrong value for flag"); exit("ERROR: Wrong value for flag");
if (!(preg_match("/^[a-z]{1,127}$/", $_POST['tag']))) if (!(preg_match("/^[a-z]{1,127}$/", $_POST['tag'])))
exit("ERROR: Wrong value for tag"); exit("ERROR: Wrong value for tag");
if (!(preg_match("/^[a-z0-9.-]{1,255}$/", $_POST['value']))) if (!(preg_match("/^[a-z0-9.-]{1,255}$/", $_POST['value'])))
exit("ERROR: Wrong value for value"); exit("ERROR: Wrong value for value");
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN CAA " . $_POST['flag'] . " " . $_POST['tag'] . " " . $_POST['value']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN CAA " . $_POST['flag'] . " " . $_POST['tag'] . " " . $_POST['value']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }

View File

@ -3,72 +3,72 @@
Afin d'activer DNSSEC, vous devez indiquer un enregistrement DS à la zone parente. Afin d'activer DNSSEC, vous devez indiquer un enregistrement DS à la zone parente.
<form method="post"> <form method="post">
<select required="" name="zone" id="zone"> <select required="" name="zone" id="zone">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$zones = nsListUserZones($_SESSION['username']); $zones = nsListUserZones($_SESSION['username']);
if ($zones) { if ($zones) {
foreach($zones as $zone) { foreach($zones as $zone) {
echo "<option value='" . $zone . "'>" . $zone . "</option>"; echo "<option value='" . $zone . "'>" . $zone . "</option>";
} }
} }
?> ?>
</select> </select>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['zone']) AND isset($_SESSION['username'])) { if (isset($_POST['zone']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
nsCheckZonePossession($_POST['zone']); nsCheckZonePossession($_POST['zone']);
exec(KEYMGR_PATH . " " . $_POST['zone'] . " ds", $output); exec(KEYMGR_PATH . " " . $_POST['zone'] . " ds", $output);
$l0 = explode(" ", $output[0]); $l0 = explode(" ", $output[0]);
$l1 = explode(" ", $output[1]); $l1 = explode(" ", $output[1]);
?> ?>
<dl> <dl>
<dt>Zone</dt> <dt>Zone</dt>
<dd> <dd>
<code><?= $_POST['zone'] ?></code> <code><?= $_POST['zone'] ?></code>
</dd> </dd>
<dt>Tag</dt> <dt>Tag</dt>
<dd> <dd>
<code><?= $l0[2] ?></code> <code><?= $l0[2] ?></code>
</dd> </dd>
<dt>Algorithme</dt> <dt>Algorithme</dt>
<dd> <dd>
<code>15</code> (Ed25519) <code>15</code> (Ed25519)
</dd> </dd>
<dt>Condensat de type <code>2</code> (SHA-256)</dt> <dt>Condensat de type <code>2</code> (SHA-256)</dt>
<dd> <dd>
<code><?= $l0[5] ?></code> <code><?= $l0[5] ?></code>
</dd> </dd>
<dt>Condensat de type <code>4</code> (SHA-384 ; optionnel)</dt> <dt>Condensat de type <code>4</code> (SHA-384 ; optionnel)</dt>
<dd> <dd>
<code><?= $l1[5] ?></code> <code><?= $l1[5] ?></code>
</dd> </dd>
</dl> </dl>
<details> <details>
<summary>Données brutes</summary> <summary>Données brutes</summary>
<code><?= $output[0] ?></code><br><code><?= $output[1] ?></code> <code><?= $output[0] ?></code><br><code><?= $output[1] ?></code>
</details> </details>
<?php } ?> <?php } ?>

View File

@ -1,61 +1,61 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<dl> <dl>
<dt><a class="nsButton" href="zone">Gérer ses zones</a></dt> <dt><a class="nsButton" href="zone">Gérer ses zones</a></dt>
<dd> <dd>
Pour qu'elle soit gérée par le serveur de noms de Niver Pour qu'elle soit gérée par le serveur de noms de Niver
</dd> </dd>
<dt><a class="nsButton" href="dnssec">Obtenir les enregistrements <abbr title="Delegation Signer">DS</abbr></a></dt> <dt><a class="nsButton" href="dnssec">Obtenir les enregistrements <abbr title="Delegation Signer">DS</abbr></a></dt>
<dd> <dd>
À indiquer à la zone parente pour activer <abbr title="Domain Name System Security Extensions">DNSSEC</abbr> À indiquer à la zone parente pour activer <abbr title="Domain Name System Security Extensions">DNSSEC</abbr>
</dd> </dd>
<dt><a class="nsButton" href="ns">Enregistrement <abbr title="Name Server">NS</abbr></a></dt> <dt><a class="nsButton" href="ns">Enregistrement <abbr title="Name Server">NS</abbr></a></dt>
<dd> <dd>
Indiquer le serveur de noms d'une zone Indiquer le serveur de noms d'une zone
</dd> </dd>
<dt><a class="nsButton" href="ip">Enregistrements A et AAAA</a></dt> <dt><a class="nsButton" href="ip">Enregistrements A et AAAA</a></dt>
<dd> <dd>
Indiquer l'adresse IP d'un domaine Indiquer l'adresse IP d'un domaine
</dd> </dd>
<dt><a class="nsButton" href="txt">Enregistrement TXT</a></dt> <dt><a class="nsButton" href="txt">Enregistrement TXT</a></dt>
<dd> <dd>
Associer du texte à un domaine Associer du texte à un domaine
</dd> </dd>
<dt><a class="nsButton" href="srv">Enregistrement SRV</a></dt> <dt><a class="nsButton" href="srv">Enregistrement SRV</a></dt>
<dd> <dd>
Indiquer un serveur pour un domaine Indiquer un serveur pour un domaine
</dd> </dd>
<dt><a class="nsButton" href="mx">Enregistrement <abbr title="Mail eXchanger">MX</abbr></a></dt> <dt><a class="nsButton" href="mx">Enregistrement <abbr title="Mail eXchanger">MX</abbr></a></dt>
<dd> <dd>
Indiquer le serveur mail pour un domaine Indiquer le serveur mail pour un domaine
</dd> </dd>
<dt><a class="nsButton" href="caa">Enregistrement <abbr title="Certification Authority Authorization">CAA</abbr></a></dt> <dt><a class="nsButton" href="caa">Enregistrement <abbr title="Certification Authority Authorization">CAA</abbr></a></dt>
<dd> <dd>
Indiquer les seules autorités de certifications autorisée à signer les domaines Indiquer les seules autorités de certifications autorisée à signer les domaines
</dd> </dd>
<dt><a class="nsButton" href="tlsa">Enregistrement <abbr title="Transport Layer Security Association">TLSA</abbr></a></dt> <dt><a class="nsButton" href="tlsa">Enregistrement <abbr title="Transport Layer Security Association">TLSA</abbr></a></dt>
<dd> <dd>
Mettre en place <abbr title="DNS-based Authentication of Named Entities">DANE</abbr> en indiquant l'empreinte d'un certificat <abbr title="Transport Layer Security">TLS</abbr> Mettre en place <abbr title="DNS-based Authentication of Named Entities">DANE</abbr> en indiquant l'empreinte d'un certificat <abbr title="Transport Layer Security">TLS</abbr>
</dd> </dd>
<dt><a class="nsButton" href="sshfp">Enregistrement <abbr title="Secure SHell FingerPrint">SSHFP</abbr></a></dt> <dt><a class="nsButton" href="sshfp">Enregistrement <abbr title="Secure SHell FingerPrint">SSHFP</abbr></a></dt>
<dd> <dd>
Indiquer les empreintes de clés <abbr title="Secure SHell">SSH</abbr> d'un domaine Indiquer les empreintes de clés <abbr title="Secure SHell">SSH</abbr> d'un domaine
</dd> </dd>
<dt><a class="nsButton" href="loc">NOT DONE : Enregistrement LOC</a></dt> <dt><a class="nsButton" href="loc">NOT DONE : Enregistrement LOC</a></dt>
<dd> <dd>
Indiquer des coordonnées géographiques Indiquer des coordonnées géographiques
</dd> </dd>
<!-- <!--
<dt><a class="nsButton" href="cname">Enregistrement <abbr title="Canonical NAME">CNAME</abbr></a></dt> <dt><a class="nsButton" href="cname">Enregistrement <abbr title="Canonical NAME">CNAME</abbr></a></dt>
<dd> <dd>
Définir un domaine comme étant l'alias d'un autre Définir un domaine comme étant l'alias d'un autre
</dd> </dd>
<dt><a class="nsButton" href="dname">Enregistrement <abbr title="Delegation NAME">DNAME</abbr></a></dt> <dt><a class="nsButton" href="dname">Enregistrement <abbr title="Delegation NAME">DNAME</abbr></a></dt>
<dd> <dd>
Définir les sous-domaines d'un domaine comme étant les alias des sous-domaines d'un autre domaine Définir les sous-domaines d'un domaine comme étant les alias des sous-domaines d'un autre domaine
</dd>--> </dd>-->
</dl> </dl>
<?php require "../bottom.inc.php"; ?> <?php require "../bottom.inc.php"; ?>

View File

@ -1,41 +1,41 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<p> <p>
Ici vous pouvez ajouter ou enlever des adresses IP dans une zone déjà enregistrée sur le serveur de noms de Niver Ici vous pouvez ajouter ou enlever des adresses IP dans une zone déjà enregistrée sur le serveur de noms de Niver
<br>Le format IPv4 (<code>A</code>) ou IPv6 (<code>AAAA</code>) sera détecté automatiquement. <br>Le format IPv4 (<code>A</code>) ou IPv6 (<code>AAAA</code>) sera détecté automatiquement.
<br>Si vous souhaitez utiliser un service d'hébergement hypertexte de Niver, voici les adresses à renseigner : <br>Si vous souhaitez utiliser un service d'hébergement hypertexte de Niver, voici les adresses à renseigner :
<br>IPv4 : <code><?= IPV4_ADDRESS ?></code> <br>IPv4 : <code><?= IPV4_ADDRESS ?></code>
<br>IPv6 : <code><?= IPV6_ADDRESS ?></code> <br>IPv6 : <code><?= IPV6_ADDRESS ?></code>
</p> </p>
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<label for="ip">Adresse IP</label><br> <label for="ip">Adresse IP</label><br>
<input required="" pattern="^[a-f0-9:.]+$" id="ip" name="ip" minlength="7" maxlength="39" size="40" type="text" placeholder="<?= IPV6_EXAMPLE ?> ou <?= IPV4_EXAMPLE ?>"><br> <input required="" pattern="^[a-f0-9:.]+$" id="ip" name="ip" minlength="7" maxlength="39" size="40" type="text" placeholder="<?= IPV6_EXAMPLE ?> ou <?= IPV4_EXAMPLE ?>"><br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['ip']) AND isset($_POST['ip'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
checkIpFormat($_POST['ip']); checkIpFormat($_POST['ip']);
if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
$record = "A"; $record = "A";
else if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) else if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
$record = "AAAA"; $record = "AAAA";
else else
exit("ERROR: unknown IP format"); exit("ERROR: unknown IP format");
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN " . $record . " " . $_POST['ip']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN " . $record . " " . $_POST['ip']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }
?> ?>

View File

@ -2,47 +2,47 @@
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="flag">Flag</label> <label for="flag">Flag</label>
<br> <br>
<input id="flag" min="0" max="127" placeholder="0" name="flag" type="number"> <input id="flag" min="0" max="127" placeholder="0" name="flag" type="number">
<br> <br>
<label for="tag">Tag</label> <label for="tag">Tag</label>
<br> <br>
<input id="tag" minlenght="1" maxlength="128" pattern="^[a-z]{1,128}$" placeholder="issue" name="tag" type="text"> <input id="tag" minlenght="1" maxlength="128" pattern="^[a-z]{1,128}$" placeholder="issue" name="tag" type="text">
<br> <br>
<label for="value">Valeur</label> <label for="value">Valeur</label>
<br> <br>
<input id="value" minlenght="3" maxlength="1024" pattern="^[a-z0-9.-]{3,1024}$" placeholder="letsencrypt.org" name="value" type="text"> <input id="value" minlenght="3" maxlength="1024" pattern="^[a-z0-9.-]{3,1024}$" placeholder="letsencrypt.org" name="value" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['flag']) AND isset($_POST['flag'])
AND isset($_POST['tag']) AND isset($_POST['tag'])
AND isset($_POST['value']) AND isset($_POST['value'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!($_POST['flag'] >= 0 AND $_POST['flag'] <= 255)) if (!($_POST['flag'] >= 0 AND $_POST['flag'] <= 255))
exit("ERROR: Wrong value for flag"); exit("ERROR: Wrong value for flag");
if (!(preg_match("/^[a-z]{1,127}$/", $_POST['tag']))) if (!(preg_match("/^[a-z]{1,127}$/", $_POST['tag'])))
exit("ERROR: Wrong value for tag"); exit("ERROR: Wrong value for tag");
if (!(preg_match("/^[a-z0-9.-]{1,255}$/", $_POST['value']))) if (!(preg_match("/^[a-z0-9.-]{1,255}$/", $_POST['value'])))
exit("ERROR: Wrong value for value"); exit("ERROR: Wrong value for value");
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN CAA " . $_POST['flag'] . " " . $_POST['tag'] . " " . $_POST['value']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN CAA " . $_POST['flag'] . " " . $_POST['tag'] . " " . $_POST['value']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }

View File

@ -2,42 +2,42 @@
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="priority">Priorité</label> <label for="priority">Priorité</label>
<br> <br>
<input id="priority" min="0" max="65535" value="0" placeholder="0" name="priority" type="number"> <input id="priority" min="0" max="65535" value="0" placeholder="0" name="priority" type="number">
<br> <br>
<label for="host">Hôte</label> <label for="host">Hôte</label>
<br> <br>
<input id="host" placeholder="mail.<?= DOMAIN_EXAMPLE ?>." name="host" type="text"> <input id="host" placeholder="mail.<?= DOMAIN_EXAMPLE ?>." name="host" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['priority']) AND isset($_POST['priority'])
AND isset($_POST['host']) AND isset($_POST['host'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 255)) if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 255))
exit("ERROR: Wrong value for priority"); exit("ERROR: Wrong value for priority");
checkAbsoluteDomainFormat($_POST['host']); checkAbsoluteDomainFormat($_POST['host']);
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN MX " . $_POST['priority'] . " " . $_POST['host']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN MX " . $_POST['priority'] . " " . $_POST['host']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }
?> ?>

View File

@ -1,28 +1,28 @@
<?php include "../top.inc.php"; ?> <?php include "../top.inc.php"; ?>
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="ns">Serveur de nom</label> <label for="ns">Serveur de nom</label>
<br> <br>
<input id="ns" placeholder="ns1.<?= DOMAIN_EXAMPLE ?>" name="ns" type="text"> <input id="ns" placeholder="ns1.<?= DOMAIN_EXAMPLE ?>" name="ns" type="text">
<br> <br>
<input value="Procéder" type="submit"> <input value="Procéder" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['ns']) AND isset($_POST['ns'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
checkAbsoluteDomainFormat($_POST['ns']); checkAbsoluteDomainFormat($_POST['ns']);
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN NS " . $_POST['ns']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN NS " . $_POST['ns']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }
?> ?>

View File

@ -2,62 +2,62 @@
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="priority">Priorité</label> <label for="priority">Priorité</label>
<br> <br>
<input id="priority" min="0" max="65535" value="0" placeholder="0" name="priority" type="number"> <input id="priority" min="0" max="65535" value="0" placeholder="0" name="priority" type="number">
<br> <br>
<label for="weight">Poids</label> <label for="weight">Poids</label>
<br> <br>
<input id="weight" min="0" max="65535" value="0" placeholder="0" name="weight" type="number"> <input id="weight" min="0" max="65535" value="0" placeholder="0" name="weight" type="number">
<br> <br>
<label for="port">Port</label> <label for="port">Port</label>
<br> <br>
<input id="port" min="0" max="65535" placeholder="32768" name="port" type="number"> <input id="port" min="0" max="65535" placeholder="32768" name="port" type="number">
<br> <br>
<label for="target">Cible</label> <label for="target">Cible</label>
<br> <br>
<input id="target" minlenght="1" maxlength="128" placeholder="service.<?= DOMAIN_EXAMPLE ?>." name="target" type="text"> <input id="target" minlenght="1" maxlength="128" placeholder="service.<?= DOMAIN_EXAMPLE ?>." name="target" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['priority']) AND isset($_POST['priority'])
AND isset($_POST['weight']) AND isset($_POST['weight'])
AND isset($_POST['port']) AND isset($_POST['port'])
AND isset($_POST['target']) AND isset($_POST['target'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 65535)) if (!($_POST['priority'] >= 0 AND $_POST['priority'] <= 65535))
exit("ERROR: Wrong value for priority"); exit("ERROR: Wrong value for priority");
if (!($_POST['weight'] >= 0 AND $_POST['weight'] <= 65535)) if (!($_POST['weight'] >= 0 AND $_POST['weight'] <= 65535))
exit("ERROR: Wrong value for weight"); exit("ERROR: Wrong value for weight");
if (!($_POST['port'] >= 0 AND $_POST['port'] <= 65535)) if (!($_POST['port'] >= 0 AND $_POST['port'] <= 65535))
exit("ERROR: Wrong value for port"); exit("ERROR: Wrong value for port");
checkAbsoluteDomainFormat($_POST['target']); checkAbsoluteDomainFormat($_POST['target']);
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN SRV " . $_POST['priority'] . " " . $_POST['weight'] . " " . $_POST['port'] . " " . $_POST['target']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN SRV " . $_POST['priority'] . " " . $_POST['weight'] . " " . $_POST['port'] . " " . $_POST['target']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }
?> ?>

View File

@ -2,59 +2,59 @@
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="algo">Algorithme</label> <label for="algo">Algorithme</label>
<br> <br>
<select required="" name="algo" id="algo"> <select required="" name="algo" id="algo">
<option value="1">1 (RSA)</option> <option value="1">1 (RSA)</option>
<option value="2" disabled="">2 (DSA)</option> <option value="2" disabled="">2 (DSA)</option>
<option value="3">3 (ECDSA)</option> <option value="3">3 (ECDSA)</option>
<option value="4" selected="">4 (ED25519)</option> <option value="4" selected="">4 (ED25519)</option>
</select> </select>
<br> <br>
<label for="type">Type de hash</label> <label for="type">Type de hash</label>
<br> <br>
<select required="" name="type" id="type"> <select required="" name="type" id="type">
<option value="1" disabled="">1 (SHA-1)</option> <option value="1" disabled="">1 (SHA-1)</option>
<option value="2" selected="">2 (SHA-256)</option> <option value="2" selected="">2 (SHA-256)</option>
</select> </select>
<br> <br>
<label for="fp">Empreinte</label> <label for="fp">Empreinte</label>
<br> <br>
<input required="" id="fp" size="65" minlenght="64" maxlength="64" placeholder="26e6bbb4796c4fb78632e737d31a8acaba43c3a92d9c047031f04e9b70826e1d" name="fp" type="text"> <input required="" id="fp" size="65" minlenght="64" maxlength="64" placeholder="26e6bbb4796c4fb78632e737d31a8acaba43c3a92d9c047031f04e9b70826e1d" name="fp" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['algo']) AND isset($_POST['algo'])
AND isset($_POST['fp']) AND isset($_POST['fp'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!($_POST['algo'] === "1" OR $_POST['algo'] === "3" OR $_POST['algo'] === "4")) if (!($_POST['algo'] === "1" OR $_POST['algo'] === "3" OR $_POST['algo'] === "4"))
exit("ERROR: Wrong value for algo"); exit("ERROR: Wrong value for algo");
if (!($_POST['type'] === "2")) if (!($_POST['type'] === "2"))
exit("ERROR: Wrong value for type"); exit("ERROR: Wrong value for type");
if (!(preg_match("/^[a-z0-9]{64}$/", $_POST['fp']))) if (!(preg_match("/^[a-z0-9]{64}$/", $_POST['fp'])))
exit("ERROR: Wrong value for fp"); exit("ERROR: Wrong value for fp");
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN SSHFP " . $_POST['algo'] . " " . $_POST['type'] . " " . $_POST['fp']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN SSHFP " . $_POST['algo'] . " " . $_POST['type'] . " " . $_POST['fp']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }
?> ?>

View File

@ -2,73 +2,73 @@
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="use">Utilisation</label> <label for="use">Utilisation</label>
<br> <br>
<select required="" name="use" id="use"> <select required="" name="use" id="use">
<option value="" selected="" disabled="">-</option> <option value="" selected="" disabled="">-</option>
<option value="0">0 (PKIX-TA, <abbr title="also known as">aka<abbr> CA constraint)</option> <option value="0">0 (PKIX-TA, <abbr title="also known as">aka<abbr> CA constraint)</option>
<option value="1">1 (PKIX-EE, <abbr title="also known as">aka<abbr> Service certificate constraint)</option> <option value="1">1 (PKIX-EE, <abbr title="also known as">aka<abbr> Service certificate constraint)</option>
<option value="2">2 (DANE-TA, <abbr title="also known as">aka<abbr> Trust Anchor Assertion)</option> <option value="2">2 (DANE-TA, <abbr title="also known as">aka<abbr> Trust Anchor Assertion)</option>
<option value="3">3 (DANE-EE, <abbr title="also known as">aka<abbr> Domain issued certificate)</option> <option value="3">3 (DANE-EE, <abbr title="also known as">aka<abbr> Domain issued certificate)</option>
</select> </select>
<br> <br>
<label for="selector">Selecteur</label> <label for="selector">Selecteur</label>
<br> <br>
<select required="" name="selector" id="selector"> <select required="" name="selector" id="selector">
<option value="" selected="" disabled="">-</option> <option value="" selected="" disabled="">-</option>
<option value="0">0 (le certificat entier doit correspondre)</option> <option value="0">0 (le certificat entier doit correspondre)</option>
<option value="1">1 (la clé publique du certificat doit correspondre)</option> <option value="1">1 (la clé publique du certificat doit correspondre)</option>
</select> </select>
<br> <br>
<label for="type">Type de correspondance</label> <label for="type">Type de correspondance</label>
<br> <br>
<select required="" name="type" id="type"> <select required="" name="type" id="type">
<option value="" selected="" disabled="">-</option> <option value="" selected="" disabled="">-</option>
<option value="0">0 (certificat entier)</option> <option value="0">0 (certificat entier)</option>
<option value="1">1 (SHA-256)</option> <option value="1">1 (SHA-256)</option>
<option value="2">2 (SHA-512)</option> <option value="2">2 (SHA-512)</option>
</select> </select>
<br> <br>
<label for="content">Contenu</label> <label for="content">Contenu</label>
<br> <br>
<input id="content" minlenght="3" maxlength="1024" pattern="^[a-zA-Z0-9.-]{3,1024}$" placeholder="gjioerjgioer" name="content" type="text"> <input id="content" minlenght="3" maxlength="1024" pattern="^[a-zA-Z0-9.-]{3,1024}$" placeholder="gjioerjgioer" name="content" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['use']) AND isset($_POST['use'])
AND isset($_POST['selector']) AND isset($_POST['selector'])
AND isset($_POST['type']) AND isset($_POST['type'])
AND isset($_POST['content']) AND isset($_POST['content'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!($_POST['use'] >= 0 AND $_POST['use'] <= 3)) if (!($_POST['use'] >= 0 AND $_POST['use'] <= 3))
exit("ERROR: Wrong value for use"); exit("ERROR: Wrong value for use");
if (!($_POST['selector'] === "0" OR $_POST['selector'] === "1")) if (!($_POST['selector'] === "0" OR $_POST['selector'] === "1"))
exit("ERROR: Wrong value for selector"); exit("ERROR: Wrong value for selector");
if (!($_POST['type'] >= 0 OR $_POST['type'] <= 2)) if (!($_POST['type'] >= 0 OR $_POST['type'] <= 2))
exit("ERROR: Wrong value for type"); exit("ERROR: Wrong value for type");
if (!(preg_match("/^[a-zA-Z0-9.-]{1,1024}$/", $_POST['content']))) if (!(preg_match("/^[a-zA-Z0-9.-]{1,1024}$/", $_POST['content'])))
exit("ERROR: Wrong value for content"); exit("ERROR: Wrong value for content");
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN TLSA " . $_POST['use'] . " " . $_POST['selector'] . " " . $_POST['type'] . " " . $_POST['content']); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . " IN TLSA " . $_POST['use'] . " " . $_POST['selector'] . " " . $_POST['type'] . " " . $_POST['content']);
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }

View File

@ -1,29 +1,29 @@
<?php include "../top.inc.php"; ?> <?php include "../top.inc.php"; ?>
<form method="post"> <form method="post">
<?php require "../inc/form/form.ns.inc.php"; ?> <?php require "../inc/form/form.ns.inc.php"; ?>
<br> <br>
<label for="txt">Texte</label> <label for="txt">Texte</label>
<br> <br>
<input id="txt" minlenght="5" maxlength="8192" pattern="^[a-zA-Z0-9 =:!%$+/\()[\]_-]{5,8192}$" placeholder="Du texte..." name="txt" type="text"> <input id="txt" minlenght="5" maxlength="8192" pattern="^[a-zA-Z0-9 =:!%$+/\()[\]_-]{5,8192}$" placeholder="Du texte..." name="txt" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (nsCommonRequirements() if (nsCommonRequirements()
AND isset($_POST['txt']) AND isset($_POST['txt'])
) { ) {
$values = nsParseCommonRequirements(); $values = nsParseCommonRequirements();
if (!(preg_match("/^[a-zA-Z0-9 =:!%$+\/\()[\]_-]{5,8192}$/", $_POST['txt']))) if (!(preg_match("/^[a-zA-Z0-9 =:!%$+\/\()[\]_-]{5,8192}$/", $_POST['txt'])))
exit("ERROR : Wrong caracter or wrong caracter quantity"); exit("ERROR : Wrong caracter or wrong caracter quantity");
exec(KNOTC_PATH . " zone-begin " . $_POST['zone']); exec(KNOTC_PATH . " zone-begin " . $_POST['zone']);
exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . ' IN TXT \"' . $_POST['txt'] . '\"'); exec(KNOTC_PATH . " zone-" . $values['action'] . "set " . $_POST['zone'] . " " . $values['domain'] . " " . $values['ttl'] . ' IN TXT \"' . $_POST['txt'] . '\"');
exec(KNOTC_PATH . " zone-commit " . $_POST['zone']); exec(KNOTC_PATH . " zone-commit " . $_POST['zone']);
echo "Enregistrement ajouté"; echo "Enregistrement ajouté";
} }
?> ?>

View File

@ -1,89 +1,89 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<form method="post"> <form method="post">
<h2>Ajouter une zone</h2> <h2>Ajouter une zone</h2>
<label for="domain">Domaine</label><br> <label for="domain">Domaine</label><br>
<input required="" placeholder="domain.<?= DOMAIN_EXAMPLE ?>." id="domain" name="domain" type="text"><br> <input required="" placeholder="domain.<?= DOMAIN_EXAMPLE ?>." id="domain" name="domain" type="text"><br>
<input value="Ajouter" type="submit"> <input value="Ajouter" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['domain']) AND isset($_SESSION['username'])) { if (isset($_POST['domain']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
checkAbsoluteDomainFormat($_POST['domain']); checkAbsoluteDomainFormat($_POST['domain']);
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$stmt = $db->prepare("INSERT INTO zones(zone, username) VALUES(:zone, :username)"); $stmt = $db->prepare("INSERT INTO zones(zone, username) VALUES(:zone, :username)");
$stmt->bindParam(':zone', $_POST['domain']); $stmt->bindParam(':zone', $_POST['domain']);
$stmt->bindParam(':username', $_SESSION['username']); $stmt->bindParam(':username', $_SESSION['username']);
$stmt->execute(); $stmt->execute();
$knotZonePath = KNOT_ZONES_PATH . "/" . $_POST['domain'] . "zone"; $knotZonePath = KNOT_ZONES_PATH . "/" . $_POST['domain'] . "zone";
$knotZone = file_get_contents(NIVER_TEMPLATE_PATH . "/knot.template"); $knotZone = file_get_contents(NIVER_TEMPLATE_PATH . "/knot.template");
$knotZone = preg_replace("/DOMAIN/", $_POST['domain'], $knotZone); $knotZone = preg_replace("/DOMAIN/", $_POST['domain'], $knotZone);
file_put_contents($knotZonePath, $knotZone); file_put_contents($knotZonePath, $knotZone);
chmod($knotZonePath, 0660); chmod($knotZonePath, 0660);
exec(KNOTC_PATH . " conf-begin"); exec(KNOTC_PATH . " conf-begin");
exec(KNOTC_PATH . " conf-set 'zone[" . $_POST['domain'] . "]'"); exec(KNOTC_PATH . " conf-set 'zone[" . $_POST['domain'] . "]'");
exec(KNOTC_PATH . " conf-set 'zone[" . $_POST['domain'] . "].template' 'niver'"); exec(KNOTC_PATH . " conf-set 'zone[" . $_POST['domain'] . "].template' 'niver'");
exec(KNOTC_PATH . " conf-commit"); exec(KNOTC_PATH . " conf-commit");
echo "La requête a été traitée."; echo "La requête a été traitée.";
} }
?> ?>
<form method="post"> <form method="post">
<h2>Supprimer une zone</h2> <h2>Supprimer une zone</h2>
<label for="zone">Zone</label> <label for="zone">Zone</label>
<select required="" name="zone" id="zone"> <select required="" name="zone" id="zone">
<option value="" disabled="" selected="">-</option><?php <option value="" disabled="" selected="">-</option><?php
$zones = nsListUserZones($_SESSION['username']); $zones = nsListUserZones($_SESSION['username']);
if (!empty($zones)) { if (!empty($zones)) {
foreach ($zones as $zone) foreach ($zones as $zone)
echo "<option value='" . $zone . "'>" . $zone . "</option>"; echo "<option value='" . $zone . "'>" . $zone . "</option>";
} }
?> ?>
</select> </select>
<br> <br>
<input value="Supprimer toutes les données liées à cette zone" type="submit"> <input value="Supprimer toutes les données liées à cette zone" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['zone']) AND isset($_SESSION['username'])) { if (isset($_POST['zone']) AND isset($_SESSION['username'])) {
nsCheckZonePossession($_POST['zone']); nsCheckZonePossession($_POST['zone']);
// Remove Knot zone file // Remove Knot zone file
unlink(KNOT_ZONES_PATH . "/" . $_POST['zone'] . "zone"); unlink(KNOT_ZONES_PATH . "/" . $_POST['zone'] . "zone");
// Remove Knot tied data // Remove Knot tied data
exec(KNOTC_PATH . " zone-purge" . $_POST['zone']); exec(KNOTC_PATH . " zone-purge" . $_POST['zone']);
// Remove from Knot configuration // Remove from Knot configuration
exec(KNOTC_PATH . " conf-begin"); exec(KNOTC_PATH . " conf-begin");
exec(KNOTC_PATH . " conf-unset 'zone[" . $_POST['domain'] . "]'"); exec(KNOTC_PATH . " conf-unset 'zone[" . $_POST['domain'] . "]'");
exec(KNOTC_PATH . " conf-commit"); exec(KNOTC_PATH . " conf-commit");
// Remove from Niver's database // Remove from Niver's database
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$stmt = $db->prepare("DELETE FROM zones WHERE zone = :zone AND username = :username"); $stmt = $db->prepare("DELETE FROM zones WHERE zone = :zone AND username = :username");
$stmt->bindParam(':zone', $_POST['zone']); $stmt->bindParam(':zone', $_POST['zone']);
$stmt->bindParam(':username', $_SESSION['username']); $stmt->bindParam(':username', $_SESSION['username']);
$stmt->execute(); $stmt->execute();
echo "La requête a été traitée."; echo "La requête a été traitée.";
} }
?> ?>

View File

@ -1,104 +1,104 @@
<?php include "../top.inc.php"; ?> <?php include "../top.inc.php"; ?>
<form method="post"> <form method="post">
<label for="action">Action</label> <label for="action">Action</label>
<select name="action" id="action"> <select name="action" id="action">
<option value="add">Ajouter</option> <option value="add">Ajouter</option>
<option value="delete">Retirer</option> <option value="delete">Retirer</option>
</select> </select>
<br> <br>
<label for="zone">Domaine</label> <label for="zone">Domaine</label>
<br> <br>
<select required="" name="zone" id="zone"> <select required="" name="zone" id="zone">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$domains = regListUserDomains($_SESSION['username']); $domains = regListUserDomains($_SESSION['username']);
if ($domains) { if ($domains) {
foreach($domains as $domain) { foreach($domains as $domain) {
echo "<option value='" . $domain . "'>" . $domain . "</option>"; echo "<option value='" . $domain . "'>" . $domain . "</option>";
} }
} }
?> ?>
</select> </select>
<br> <br>
<label for="keytag">Tag de la clé</label> <label for="keytag">Tag de la clé</label>
<br> <br>
<input required="" id="keytag" placeholder="32768" min="1" max="65535" name="keytag" type="number"><span></span> <input required="" id="keytag" placeholder="32768" min="1" max="65535" name="keytag" type="number"><span></span>
<br> <br>
<label for="algo">Algorithme</label> <label for="algo">Algorithme</label>
<br> <br>
<select required="" name="algo" id="algo"> <select required="" name="algo" id="algo">
<!-- RFC 8624 : Algorithm Implementation Requirements and Usage Guidance for DNSSEC > Algorithm Selection > DNSKEY Algorithms --> <!-- RFC 8624 : Algorithm Implementation Requirements and Usage Guidance for DNSSEC > Algorithm Selection > DNSKEY Algorithms -->
<!-- https://tools.ietf.org/html/rfc8624.html#section-3.1 --> <!-- https://tools.ietf.org/html/rfc8624.html#section-3.1 -->
<option value="1" disabled="">1 (RSAMD5)</option> <option value="1" disabled="">1 (RSAMD5)</option>
<option value="3" disabled="">3 (DSA)</option> <option value="3" disabled="">3 (DSA)</option>
<option value="5" disabled="">5 (RSASHA1)</option> <option value="5" disabled="">5 (RSASHA1)</option>
<option value="6" disabled="">6 (DSA-NSEC3-SHA1)</option> <option value="6" disabled="">6 (DSA-NSEC3-SHA1)</option>
<option value="7" disabled="">7 (RSASHA1-NSEC3-SHA1)</option> <option value="7" disabled="">7 (RSASHA1-NSEC3-SHA1)</option>
<option value="8">8 (RSASHA256)</option> <option value="8">8 (RSASHA256)</option>
<option value="10" disabled="">10 (RSASHA512)</option> <option value="10" disabled="">10 (RSASHA512)</option>
<option value="12" disabled="">12 (ECC-GOST)</option> <option value="12" disabled="">12 (ECC-GOST)</option>
<option value="13">13 (ECDSAP256SHA256)</option> <option value="13">13 (ECDSAP256SHA256)</option>
<option value="14">14 (ECDSAP384SHA384)</option> <option value="14">14 (ECDSAP384SHA384)</option>
<option value="15" selected="">15 (ED25519)</option> <option value="15" selected="">15 (ED25519)</option>
<option value="16">16 (ED448)</option> <option value="16">16 (ED448)</option>
</select> </select>
<br> <br>
<label for="dt">Type de condensat</label> <label for="dt">Type de condensat</label>
<br> <br>
<select required="" name="dt" id="dt"> <select required="" name="dt" id="dt">
<!-- RFC 8624 : Algorithm Implementation Requirements and Usage Guidance for DNSSEC > Algorithm Selection > DS and CDS Algorithms --> <!-- RFC 8624 : Algorithm Implementation Requirements and Usage Guidance for DNSSEC > Algorithm Selection > DS and CDS Algorithms -->
<!-- https://tools.ietf.org/html/rfc8624.html#section-3.3 --> <!-- https://tools.ietf.org/html/rfc8624.html#section-3.3 -->
<option value="1" disabled="">1 (SHA-1)</option> <option value="1" disabled="">1 (SHA-1)</option>
<option value="2" selected="">2 (SHA-256)</option> <option value="2" selected="">2 (SHA-256)</option>
<option value="3" disabled="">3 (GOST R 34.11-94)</option> <option value="3" disabled="">3 (GOST R 34.11-94)</option>
<option value="4">4 (SHA-384)</option> <option value="4">4 (SHA-384)</option>
</select> </select>
<br> <br>
<label for="key">Delegation Signer</label> <label for="key">Delegation Signer</label>
<br> <br>
<input id="key" required="" name="key" type="text" placeholder="018F25E4A022463478C9E30136EC53771A1704A0F0B3CE5B883AC9C8A6A55D16B638B4DE70662ACA5295D3669E7CADD9"> <input id="key" required="" name="key" type="text" placeholder="018F25E4A022463478C9E30136EC53771A1704A0F0B3CE5B883AC9C8A6A55D16B638B4DE70662ACA5295D3669E7CADD9">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['zone']) AND isset($_POST['keytag']) AND isset($_POST['algo']) AND isset($_POST['key']) AND isset($_SESSION['username'])) { if (isset($_POST['zone']) AND isset($_POST['keytag']) AND isset($_POST['algo']) AND isset($_POST['key']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
if (!($_POST['algo'] === "8") if (!($_POST['algo'] === "8")
AND !($_POST['algo'] === "13") AND !($_POST['algo'] === "13")
AND !($_POST['algo'] === "14") AND !($_POST['algo'] === "14")
AND !($_POST['algo'] === "15") AND !($_POST['algo'] === "15")
AND !($_POST['algo'] === "16") AND !($_POST['algo'] === "16")
) )
exit("Wrong value for algo"); exit("Wrong value for algo");
$_POST['keytag'] = intval($_POST['keytag']); $_POST['keytag'] = intval($_POST['keytag']);
if ((!preg_match("/^[0-9]{1,6}$/", $_POST['keytag'])) OR !($_POST['keytag'] >= 1) OR !($_POST['keytag'] <= 65535)) if ((!preg_match("/^[0-9]{1,6}$/", $_POST['keytag'])) OR !($_POST['keytag'] >= 1) OR !($_POST['keytag'] <= 65535))
exit("Wrong value for keytag"); exit("Wrong value for keytag");
if (!$_POST['dt'] === "2" AND !$_POST['dt'] === "4") if (!$_POST['dt'] === "2" AND !$_POST['dt'] === "4")
exit("Wrong value for dt"); exit("Wrong value for dt");
checkAbsoluteDomainFormat($_POST['zone']); checkAbsoluteDomainFormat($_POST['zone']);
nsCheckZonePossession($_POST['zone']); nsCheckZonePossession($_POST['zone']);
regCheckDomainPossession($_POST['zone']); regCheckDomainPossession($_POST['zone']);
$action = checkAction($_POST['action']); $action = checkAction($_POST['action']);
$suffix = regGetUpperDomain($_POST['zone']); $suffix = regGetUpperDomain($_POST['zone']);
exec(KNOTC_PATH . " zone-begin " . $suffix); exec(KNOTC_PATH . " zone-begin " . $suffix);
exec(KNOTC_PATH . " zone-" . $action . "set " . $suffix . " " . $_POST['zone'] . " 86400 IN DS " . $_POST['keytag'] . " " . $_POST['algo'] . " " . $_POST['dt'] . " " . $_POST['key']); exec(KNOTC_PATH . " zone-" . $action . "set " . $suffix . " " . $_POST['zone'] . " 86400 IN DS " . $_POST['keytag'] . " " . $_POST['algo'] . " " . $_POST['dt'] . " " . $_POST['key']);
exec(KNOTC_PATH . " zone-commit " . $suffix); exec(KNOTC_PATH . " zone-commit " . $suffix);
echo "La requête a été envoyée à Knot"; echo "La requête a été envoyée à Knot";
} }

View File

@ -1,77 +1,77 @@
<?php require "../top.inc.php"; ?> <?php require "../top.inc.php"; ?>
<form method="post"> <form method="post">
<label for="action">Action</label> <label for="action">Action</label>
<select name="action" id="action"> <select name="action" id="action">
<option value="add">Ajouter</option> <option value="add">Ajouter</option>
<option value="delete">Retirer</option> <option value="delete">Retirer</option>
</select> </select>
<fieldset> <fieldset>
<legend>Domaine</legend> <legend>Domaine</legend>
<div class="elForm"> <div class="elForm">
<label for="subdomain">Sous-domaine</label> <label for="subdomain">Sous-domaine</label>
<br> <br>
<input required="" id="subdomain" placeholder="ns1" name="subdomain" type="text"> <input required="" id="subdomain" placeholder="ns1" name="subdomain" type="text">
</div> </div>
<div class="elForm"> <div class="elForm">
<label for="suffix">Domaine</label> <label for="suffix">Domaine</label>
<br> <br>
<select required="" name="suffix" id="suffix"> <select required="" name="suffix" id="suffix">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$suffixes = regListUserDomains($_SESSION['username']); $suffixes = regListUserDomains($_SESSION['username']);
if ($suffixes) { if ($suffixes) {
foreach($suffixes as $suffix) { foreach($suffixes as $suffix) {
echo "<option value='" . $suffix . "'>." . $suffix . "</option>"; echo "<option value='" . $suffix . "'>." . $suffix . "</option>";
} }
} }
?> ?>
</select> </select>
</div> </div>
</fieldset> </fieldset>
<label for="ip">IP</label><br> <label for="ip">IP</label><br>
<input required="" pattern="^[a-f0-9:.]+$" id="ip" name="ip" minlength="7" maxlength="39" size="40" type="text" placeholder="<?= IPV4_EXAMPLE ?> ou <?= IPV6_EXAMPLE ?>"> <input required="" pattern="^[a-f0-9:.]+$" id="ip" name="ip" minlength="7" maxlength="39" size="40" type="text" placeholder="<?= IPV4_EXAMPLE ?> ou <?= IPV6_EXAMPLE ?>">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['action']) AND isset($_POST['subdomain']) AND isset($_POST['suffix']) AND isset($_POST['ip']) AND isset($_SESSION['username'])) { if (isset($_POST['action']) AND isset($_POST['subdomain']) AND isset($_POST['suffix']) AND isset($_POST['ip']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
if (!$suffixes) if (!$suffixes)
exit("ERROR : You don't own any domain"); exit("ERROR : You don't own any domain");
if (!in_array($_POST['suffix'], $suffixes)) if (!in_array($_POST['suffix'], $suffixes))
exit("ERROR : You don't own this suffix"); exit("ERROR : You don't own this suffix");
$domain = $_POST['subdomain'] . "." . $_POST['suffix']; $domain = $_POST['subdomain'] . "." . $_POST['suffix'];
checkAbsoluteDomainFormat($domain); checkAbsoluteDomainFormat($domain);
checkIpFormat($_POST['ip']); checkIpFormat($_POST['ip']);
if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4))
$record = "A"; $record = "A";
else if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) else if (filter_var($_POST['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6))
$record = "AAAA"; $record = "AAAA";
else else
exit("Unknown error about IP format"); exit("Unknown error about IP format");
$action = checkAction($_POST['action']); $action = checkAction($_POST['action']);
$publicSuffix = regGetUpperDomain($_POST['suffix']); $publicSuffix = regGetUpperDomain($_POST['suffix']);
exec(KNOTC_PATH . " zone-begin " . $publicSuffix); exec(KNOTC_PATH . " zone-begin " . $publicSuffix);
exec(KNOTC_PATH . " zone-" . $action . "set " . $publicSuffix . " " . $domain . " 86400 IN " . $record . " " . $_POST['ip']); exec(KNOTC_PATH . " zone-" . $action . "set " . $publicSuffix . " " . $domain . " 86400 IN " . $record . " " . $_POST['ip']);
exec(KNOTC_PATH . " zone-commit " . $publicSuffix); exec(KNOTC_PATH . " zone-commit " . $publicSuffix);
echo "Glue record ajouté"; echo "Glue record ajouté";
} }
?> ?>

View File

@ -1,22 +1,22 @@
<?php include "../top.inc.php"; ?> <?php include "../top.inc.php"; ?>
<dl> <dl>
<dt><a class="regButton" href="register">Enregistrer un nouveau domaine</a></dt> <dt><a class="regButton" href="register">Enregistrer un nouveau domaine</a></dt>
<dd> <dd>
Prendre possession d'un sous-domaine de <code><?= REGISTRY ?></code> Prendre possession d'un sous-domaine de <code><?= REGISTRY ?></code>
</dd> </dd>
<dt><a class="regButton" href="ns">Enregistrement <abbr title="Name Server">NS</abbr></a></dt> <dt><a class="regButton" href="ns">Enregistrement <abbr title="Name Server">NS</abbr></a></dt>
<dd> <dd>
Indiquer les serveurs de noms de son sous-domaine de <code><?= REGISTRY ?></code> Indiquer les serveurs de noms de son sous-domaine de <code><?= REGISTRY ?></code>
</dd> </dd>
<dt><a class="regButton" href="ds">Enregistrement <abbr title="Delegation Signer">DS</abbr></a></dt> <dt><a class="regButton" href="ds">Enregistrement <abbr title="Delegation Signer">DS</abbr></a></dt>
<dd> <dd>
Déléguer la confiance <abbr title="Domain Name System Security Extensions">DNSSEC</abbr> Déléguer la confiance <abbr title="Domain Name System Security Extensions">DNSSEC</abbr>
</dd> </dd>
<dt><a class="regButton" href="glue">Glue Record</a></dt> <dt><a class="regButton" href="glue">Glue Record</a></dt>
<dd> <dd>
Indiquer les IP de ses serveurs de noms de son sous-domaine de <code><?= REGISTRY ?></code> dont les adresses se trouvent sur ce même sous-domaine Indiquer les IP de ses serveurs de noms de son sous-domaine de <code><?= REGISTRY ?></code> dont les adresses se trouvent sur ce même sous-domaine
</dd> </dd>
</dl> </dl>
<?php include "../bottom.inc.php"; ?> <?php include "../bottom.inc.php"; ?>

View File

@ -1,64 +1,64 @@
<?php include "../top.inc.php"; ?> <?php include "../top.inc.php"; ?>
<form method="post"> <form method="post">
<label for="action">Action</label> <label for="action">Action</label>
<select name="action" id="action"> <select name="action" id="action">
<option value="add">Ajouter</option> <option value="add">Ajouter</option>
<option value="delete">Retirer</option> <option value="delete">Retirer</option>
</select> </select>
<br> <br>
<label for="domain">Domaine</label> <label for="domain">Domaine</label>
<br> <br>
<select required="" name="domain" id="domain"> <select required="" name="domain" id="domain">
<option value="" disabled="" selected="">---</option> <option value="" disabled="" selected="">---</option>
<?php <?php
$domains = regListUserDomains($_SESSION['username']); $domains = regListUserDomains($_SESSION['username']);
if ($domains) { if ($domains) {
foreach($domains as $domain) { foreach($domains as $domain) {
echo "<option value='" . $domain . "'>" . $domain . "</option>"; echo "<option value='" . $domain . "'>" . $domain . "</option>";
} }
} }
?> ?>
</select> </select>
<br> <br>
<label for="ns">Serveur de nom</label> <label for="ns">Serveur de nom</label>
<br> <br>
<input id="ns" placeholder="ns1.<?= DOMAIN_EXAMPLE ?>." name="ns" type="text"> <input id="ns" placeholder="ns1.<?= DOMAIN_EXAMPLE ?>." name="ns" type="text">
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['domain']) AND isset($_POST['action']) AND isset($_POST['ns']) AND isset($_SESSION['username'])) { if (isset($_POST['domain']) AND isset($_POST['action']) AND isset($_POST['ns']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
regCheckDomainPossession($_POST['domain']); regCheckDomainPossession($_POST['domain']);
checkAbsoluteDomainFormat($_POST['ns']); checkAbsoluteDomainFormat($_POST['ns']);
$action = checkAction($_POST['action']); $action = checkAction($_POST['action']);
$suffix = regGetUpperDomain($_POST['domain']); $suffix = regGetUpperDomain($_POST['domain']);
exec(KNOTC_PATH . " zone-begin " . $suffix, $output); exec(KNOTC_PATH . " zone-begin " . $suffix, $output);
exec(KNOTC_PATH . " zone-" . $action . "set " . $suffix . " " . $_POST['domain'] . " 86400 IN NS " . $_POST['ns'], $output); exec(KNOTC_PATH . " zone-" . $action . "set " . $suffix . " " . $_POST['domain'] . " 86400 IN NS " . $_POST['ns'], $output);
exec(KNOTC_PATH . " zone-commit " . $suffix, $output); exec(KNOTC_PATH . " zone-commit " . $suffix, $output);
foreach ($output as $line) { foreach ($output as $line) {
if ($line !== "OK") { if ($line !== "OK") {
$error = true; $error = true;
} }
} }
if ($error) { if ($error) {
appendLog($output); appendLog($output);
echo "An ERROR occured!"; echo "An ERROR occured!";
} else { } else {
echo "Modification effectuée avec succès"; echo "Modification effectuée avec succès";
} }
} }
?> ?>

View File

@ -5,61 +5,61 @@ Ce domaine doit être composé uniquement d'au moins 4 lettres latines non accen
<br> <br>
<br> <br>
<form method="post"> <form method="post">
<fieldset> <fieldset>
<legend>Domaine</legend> <legend>Domaine</legend>
<div> <div>
<label for="subdomain">Sous-domaine</label> <label for="subdomain">Sous-domaine</label>
<br> <br>
<input id="subdomain" pattern="<?= SUBDOMAIN_REGEX ?>" required="" placeholder="niver" name="subdomain" type="text"> <input id="subdomain" pattern="<?= SUBDOMAIN_REGEX ?>" required="" placeholder="niver" name="subdomain" type="text">
</div> </div>
<div> <div>
<label for="suffix">Suffixe</label> <label for="suffix">Suffixe</label>
<br> <br>
<select required="" id="suffix" name="suffix"> <select required="" id="suffix" name="suffix">
<option selected="" value="<?= REGISTRY ?>">.<?= REGISTRY ?></option> <option selected="" value="<?= REGISTRY ?>">.<?= REGISTRY ?></option>
</select> </select>
</div> </div>
</fieldset> </fieldset>
<br> <br>
<input value="Valider" type="submit"> <input value="Valider" type="submit">
</form> </form>
<?php <?php
if (isset($_POST['subdomain']) AND isset($_POST['suffix']) AND isset($_SESSION['username'])) { if (isset($_POST['subdomain']) AND isset($_POST['suffix']) AND isset($_SESSION['username'])) {
antiCSRF(); antiCSRF();
if (preg_match("/" . SUBDOMAIN_REGEX . "/", $_POST['subdomain'])) { if (preg_match("/" . SUBDOMAIN_REGEX . "/", $_POST['subdomain'])) {
if (!in_array($_POST['suffix'], SUFFIXES)) if (!in_array($_POST['suffix'], SUFFIXES))
exit("Wrong value for suffix"); exit("Wrong value for suffix");
$domain = $_POST['subdomain'] . "." . $_POST['suffix']; $domain = $_POST['subdomain'] . "." . $_POST['suffix'];
checkAbsoluteDomainFormat($domain); checkAbsoluteDomainFormat($domain);
if (regIsFree($domain)) { if (regIsFree($domain)) {
$db = new PDO('sqlite:' . DB_PATH); $db = new PDO('sqlite:' . DB_PATH);
$stmt = $db->prepare("INSERT INTO registry(domain, username, last_renewal) VALUES(:domain, :username, :last_renewal)"); $stmt = $db->prepare("INSERT INTO registry(domain, username, last_renewal) VALUES(:domain, :username, :last_renewal)");
$username = $_SESSION['username']; $username = $_SESSION['username'];
$time = date("Y-m-d H:i:s"); $time = date("Y-m-d H:i:s");
$stmt->bindParam(':domain', $domain); $stmt->bindParam(':domain', $domain);
$stmt->bindParam(':username', $username); $stmt->bindParam(':username', $username);
$stmt->bindParam(':last_renewal', $time); $stmt->bindParam(':last_renewal', $time);
$stmt->execute(); $stmt->execute();
echo "Nouveau domaine enregistré"; echo "Nouveau domaine enregistré";
} else { } else {
echo "Le domaine " . $domain . " n'est pas disponible à l'enregistrement. Il est réservé ou déjà enregistré."; echo "Le domaine " . $domain . " n'est pas disponible à l'enregistrement. Il est réservé ou déjà enregistré.";
} }
} else { } else {
echo "Erreur : Le nom de domaine doit être composé uniquement d'entre 4 et 63 lettres minuscules (a-z)"; echo "Erreur : Le nom de domaine doit être composé uniquement d'entre 4 et 63 lettres minuscules (a-z)";
} }
} }
?> ?>

View File

@ -1,6 +1,6 @@
<?php <?php
if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false) if (strpos($_SERVER['PHP_SELF'], "inc.php") !== false)
exit("This file is meant to be included."); exit("This file is meant to be included.");
require "inc/const.inc.php"; require "inc/const.inc.php";
// Functions usefull everywhere // Functions usefull everywhere
@ -16,32 +16,32 @@ require "inc/pages.inc.php";
// Session initialisation (with cookies) // Session initialisation (with cookies)
if ( if (
isset($_COOKIE['niver']) // Resume session isset($_COOKIE['niver']) // Resume session
OR OR
(SERVICE === "auth" // Create new session (SERVICE === "auth" // Create new session
AND PAGE === "login" AND PAGE === "login"
AND isset($_POST['username'])) AND isset($_POST['username']))
) { ) {
session_start([ session_start([
'name' => 'niver', 'name' => 'niver',
'sid_length' => 64, 'sid_length' => 64,
'sid_bits_per_character' => 6, 'sid_bits_per_character' => 6,
'cookie_secure' => true, 'cookie_secure' => true,
'cookie_httponly' => true, 'cookie_httponly' => true,
'cookie_samesite' => 'Strict', 'cookie_samesite' => 'Strict',
'cookie_path' => PREFIX . '/', 'cookie_path' => PREFIX . '/',
'cookie_lifetime' => 432000, // = 60*60*24*5 = 5 days 'cookie_lifetime' => 432000, // = 60*60*24*5 = 5 days
'gc_maxlifetime' => 10800, 'gc_maxlifetime' => 10800,
'use_strict_mode' => true, 'use_strict_mode' => true,
'use_cookies' => true, 'use_cookies' => true,
'use_only_cookies' => true, 'use_only_cookies' => true,
]); ]);
} }
// Remove .php from URL (if any) // Remove .php from URL (if any)
if (substr($_SERVER['REQUEST_URI'], -4) == ".php") { if (substr($_SERVER['REQUEST_URI'], -4) == ".php") {
header("Location: " . PREFIX . "/" . SERVICE . "/" . PAGE, true, 301); // 301 Moved Permanently header("Location: " . PREFIX . "/" . SERVICE . "/" . PAGE, true, 301); // 301 Moved Permanently
exit; exit;
} }
// Less > CSS compilation // Less > CSS compilation
@ -56,47 +56,47 @@ $relativeLessFiles = array_flip($relativeLessFiles);
// Change relative paths into absolute paths // Change relative paths into absolute paths
foreach ($relativeLessFiles as $relativeLessFile => $nothing) { foreach ($relativeLessFiles as $relativeLessFile => $nothing) {
$absoluteLessFiles[ROOT_PATH . "/less/" . $relativeLessFile] = ""; $absoluteLessFiles[ROOT_PATH . "/less/" . $relativeLessFile] = "";
} }
// Generate one minified CSS file into css/ from sources in less/ // Generate one minified CSS file into css/ from sources in less/
$options = array( $options = array(
'cache_dir' => ROOT_PATH . '/css/', 'cache_dir' => ROOT_PATH . '/css/',
'compress' => true 'compress' => true
); );
$cssFileName = Less_Cache::Get($absoluteLessFiles, $options, THEME); $cssFileName = Less_Cache::Get($absoluteLessFiles, $options, THEME);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fr"> <html lang="fr">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title><?php <title><?php
if (isset($page['title']) AND $page['title'] != "Accueil") if (isset($page['title']) AND $page['title'] != "Accueil")
echo $page['title'] . " · "; echo $page['title'] . " · ";
if (isset($page['service'])) { if (isset($page['service'])) {
echo $page['service'] . " · "; echo $page['service'] . " · ";
} ?>Niver</title> } ?>Niver</title>
<link type="text/css" rel="stylesheet" href="<?= PREFIX ?>/css/<?= $cssFileName ?>"> <link type="text/css" rel="stylesheet" href="<?= PREFIX ?>/css/<?= $cssFileName ?>">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
</head> </head>
<body> <body>
<header> <header>
<nav> <nav>
<a href="<?= PREFIX ?>/">Niver</a><?php <a href="<?= PREFIX ?>/">Niver</a><?php
if (isset($page['service'])) { if (isset($page['service'])) {
echo ' > <a href="./">' . $page['service'] . '</a>'; echo ' > <a href="./">' . $page['service'] . '</a>';
} }
if (PAGE != "index") if (PAGE != "index")
echo ' > <a href="' . PAGE . '">' . $page['title'] . "</a>"; echo ' > <a href="' . PAGE . '">' . $page['title'] . "</a>";
?> ?>
</nav> </nav>
<?php if (isset($page['title'])) { ?> <?php if (isset($page['title'])) { ?>
<h1><?= $page['title'] ?></h1> <h1><?= $page['title'] ?></h1>
<?php } ?> <?php } ?>
</header> </header>
<main> <main>