Use a token to link account to external resource
This commit is contained in:
parent
01d5dff22b
commit
ba18c13747
|
@ -136,3 +136,27 @@ function equalArrays($a, $b) {
|
||||||
function linkToDocs($ref, $title) {
|
function linkToDocs($ref, $title) {
|
||||||
return '<a rel="help" href="' . CONF['common']['docs_prefix'] . $ref . '.html">' . $title . '</a>';
|
return '<a rel="help" href="' . CONF['common']['docs_prefix'] . $ref . '.html">' . $title . '</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This token authenticates the user to the server through a public communication (the DNS).
|
||||||
|
It is therefore also designed to keep private:
|
||||||
|
- the user's id
|
||||||
|
- that a same user used a token multiple times (by using a unique salt for each token)
|
||||||
|
*/
|
||||||
|
define('SECRET_KEY_FILE', sys_get_temp_dir() . '/Niver.key');
|
||||||
|
if (!file_exists(SECRET_KEY_FILE)) {
|
||||||
|
$original_umask = umask(0077);
|
||||||
|
file_put_contents(SECRET_KEY_FILE, random_bytes(32));
|
||||||
|
umask($original_umask);
|
||||||
|
}
|
||||||
|
define('SECRET_KEY', file_get_contents(SECRET_KEY_FILE));
|
||||||
|
function getAuthToken() {
|
||||||
|
$salt = bin2hex(random_bytes(4));
|
||||||
|
$hash = hash_hmac('sha256', $salt . ($_SESSION['username'] ?? ''), SECRET_KEY);
|
||||||
|
return $salt . '-' . substr($hash, 0, 32);
|
||||||
|
}
|
||||||
|
function checkAuthToken($salt, $hash) {
|
||||||
|
$correctProof = substr(hash_hmac('sha256', $salt . $_SESSION['username'], SECRET_KEY), 0, 32);
|
||||||
|
if (hash_equals($correctProof, $hash) !== true)
|
||||||
|
output(403, 'Preuve incorrecte');
|
||||||
|
}
|
||||||
|
|
|
@ -16,16 +16,24 @@ if (processForm()) {
|
||||||
|
|
||||||
$remoteAaaaRecords = dns_get_record($_POST['domain'], DNS_AAAA);
|
$remoteAaaaRecords = dns_get_record($_POST['domain'], DNS_AAAA);
|
||||||
if (is_array($remoteAaaaRecords) !== true)
|
if (is_array($remoteAaaaRecords) !== true)
|
||||||
output(403, 'Ce domaine n\'existe pas.');
|
output(500, 'Erreur lors de la récupération de l\'enregistrement AAAA.');
|
||||||
if (equalArrays([CONF['ht']['ipv6_address']], array_column($remoteAaaaRecords, 'ipv6')) !== true)
|
if (equalArrays([CONF['ht']['ipv6_address']], array_column($remoteAaaaRecords, 'ipv6')) !== true)
|
||||||
output(403, 'Ce domaine doit avoir pour unique enregistrement AAAA <code>' . CONF['ht']['ipv6_address'] . '</code>.');
|
output(403, 'Ce domaine doit avoir pour unique enregistrement AAAA <code>' . CONF['ht']['ipv6_address'] . '</code>.');
|
||||||
|
|
||||||
$remoteARecords = dns_get_record($_POST['domain'], DNS_A);
|
$remoteARecords = dns_get_record($_POST['domain'], DNS_A);
|
||||||
if (is_array($remoteARecords) !== true)
|
if (is_array($remoteARecords) !== true)
|
||||||
output(403, 'Ce domaine n\'existe pas.');
|
output(500, 'Erreur lors de la récupération de l\'enregistrement A.');
|
||||||
if (equalArrays([CONF['ht']['ipv4_address']], array_column($remoteARecords, 'ip')) !== true)
|
if (equalArrays([CONF['ht']['ipv4_address']], array_column($remoteARecords, 'ip')) !== true)
|
||||||
output(403, 'Ce domaine doit avoir pour unique enregistrement A <code>' . CONF['ht']['ipv4_address'] . '</code>.');
|
output(403, 'Ce domaine doit avoir pour unique enregistrement A <code>' . CONF['ht']['ipv4_address'] . '</code>.');
|
||||||
|
|
||||||
|
$remoteTXTRecords = dns_get_record($_POST['domain'], DNS_TXT);
|
||||||
|
if (is_array($remoteTXTRecords) !== true)
|
||||||
|
output(500, 'Erreur lors de la récupération de l\'enregistrement TXT.');
|
||||||
|
if (preg_match('/\nauth-owner=([0-9a-f]{8})-([0-9a-f]{32})\n/', "\n" . implode("\n", array_column($remoteTXTRecords, 'txt')) . "\n", $matches) !== 1)
|
||||||
|
output(403, 'Aucun enregistrement TXT au format correct trouvé.');
|
||||||
|
|
||||||
|
checkAuthToken($matches[1], $matches[2]);
|
||||||
|
|
||||||
rateLimit();
|
rateLimit();
|
||||||
|
|
||||||
addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "http");
|
addSite($_SESSION['username'], $_POST['dir'], $_POST['domain'], "dns", "http");
|
||||||
|
@ -57,6 +65,8 @@ if (processForm()) {
|
||||||
output(200, 'Accès HTTP par domaine ajouté sur ce dossier !');
|
output(200, 'Accès HTTP par domaine ajouté sur ce dossier !');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$proof = getAuthToken();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -64,19 +74,24 @@ if (processForm()) {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Le domaine doit contenir ces enregistrements :
|
La présence des enregistrements ci-après sera vérifiée lors du traitement de ce formulaire.
|
||||||
<dl>
|
|
||||||
<dt><code>AAAA</code></dt>
|
|
||||||
<dd>
|
|
||||||
<code><?= CONF['ht']['ipv6_address'] ?></code>
|
|
||||||
</dd>
|
|
||||||
<dt><code>A</code></dt>
|
|
||||||
<dd>
|
|
||||||
<code><?= CONF['ht']['ipv4_address'] ?></code>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><code>AAAA</code></dt>
|
||||||
|
<dd>
|
||||||
|
<code><?= CONF['ht']['ipv6_address'] ?></code>
|
||||||
|
</dd>
|
||||||
|
<dt><code>A</code></dt>
|
||||||
|
<dd>
|
||||||
|
<code><?= CONF['ht']['ipv4_address'] ?></code>
|
||||||
|
</dd>
|
||||||
|
<dt><code>TXT</code></dt>
|
||||||
|
<dd>
|
||||||
|
<code>auth-owner=<?= $proof ?></code>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
<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.<?= PLACEHOLDER_DOMAIN ?>" id="domain" name="domain" type="text"><br>
|
<input required="" placeholder="site.<?= PLACEHOLDER_DOMAIN ?>" id="domain" name="domain" type="text"><br>
|
||||||
|
|
|
@ -6,13 +6,17 @@ if (processForm()) {
|
||||||
if (query('select', 'zones', ['zone' => $_POST['domain']], 'zone') !== [])
|
if (query('select', 'zones', ['zone' => $_POST['domain']], 'zone') !== [])
|
||||||
output(403, 'Cette zone existe déjà sur ce service.');
|
output(403, 'Cette zone existe déjà sur ce service.');
|
||||||
|
|
||||||
exec(CONF['ns']['kdig_path'] . " " . ltrim(strstr($_POST['domain'], '.'), '.') . " NS +short", $parentAuthoritatives);
|
exec(CONF['ns']['kdig_path'] . ' ' . ltrim(strstr($_POST['domain'], '.'), '.') . ' NS +short', $parentAuthoritatives);
|
||||||
|
if ($parentAuthoritatives === [])
|
||||||
|
output(403, 'Serveurs de noms de la zone parente introuvables');
|
||||||
foreach ($parentAuthoritatives as $parentAuthoritative)
|
foreach ($parentAuthoritatives as $parentAuthoritative)
|
||||||
checkAbsoluteDomainFormat($parentAuthoritative);
|
checkAbsoluteDomainFormat($parentAuthoritative);
|
||||||
exec(CONF['ns']['kdig_path'] . " " . $_POST['domain'] . " NS @" . $parentAuthoritatives[0], $results);
|
|
||||||
preg_match_all('/' . preg_quote($_POST['domain'], '/') . '[\t ]+[0-9]{1,8}[\t ]+IN[\t ]+NS[\t ]+(.+)\n/', implode("\n", $results), $matches);
|
exec(CONF['ns']['kdig_path'] . ' ' . $_POST['domain'] . " NS @" . $parentAuthoritatives[0], $results);
|
||||||
if (equalArrays(CONF['ns']['servers'], $matches[1]) !== true)
|
if (preg_match('/\n' . preg_quote($_POST['domain'], '/') . '[\t ]+[0-9]{1,8}[\t ]+IN[\t ]+NS[\t ]+([0-9a-f]{8})-([0-9a-f]{32})\.auth-owner.+\n/', implode("\n", $results), $matches) !== 1)
|
||||||
output(403, 'Les serveurs ayant autorité dans cette zone indiqués par la zone parente ne sont pas ceux de Niver.');
|
output(403, 'Enregistrement d\'authentification introuvable');
|
||||||
|
|
||||||
|
checkAuthToken($matches[1], $matches[2]);
|
||||||
|
|
||||||
rateLimit();
|
rateLimit();
|
||||||
|
|
||||||
|
@ -38,10 +42,16 @@ if (processForm()) {
|
||||||
output(200, 'La requête a été traitée.');
|
output(200, 'La requête a été traitée.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$proof = getAuthToken();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Le domaine doit avoir pour enregistrements NS :
|
Le domaine doit avoir un <?= linkToDocs('ns-record', 'enregistrement NS') ?> qui commence par <code><?= $proof ?>.auth-owner</code> lors du traitement de ce formulaire.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
La zone sera servie par ces serveurs de noms :
|
||||||
<ul>
|
<ul>
|
||||||
<?php
|
<?php
|
||||||
foreach (CONF['ns']['servers'] as $server)
|
foreach (CONF['ns']['servers'] as $server)
|
||||||
|
|
Loading…
Reference in New Issue