mirror of
https://github.com/JMP-MS/ASPIC.git
synced 2026-10-27 18:17:09 +00:00
84 lines
3.9 KiB
PHP
84 lines
3.9 KiB
PHP
<?php
|
|
/**
|
|
* ASPIC — espace_utilisateur.php
|
|
*
|
|
* Résolution de l'espace disque privé de chaque utilisateur (11 septembre
|
|
* 2026, feuille de route "BackOffice" point 2). Reprend, en l'affinant, une
|
|
* proposition initiale de Jean-Marc (hacher le nom de l'instance/de la base
|
|
* en SHA256 tronqué) — écartée en cours de discussion : SHA256 est un hash
|
|
* RAPIDE, donc trivialement cassable par dictionnaire dès que l'univers des
|
|
* valeurs possibles est petit et connu (les noms d'instances/bases ASPIC ne
|
|
* sont ni nombreux ni secrets). La bonne pièce existe déjà dans ce projet :
|
|
* `LIEN_DOC_CLE_SECRETE` (voir prospects_core.php, fabriquerJetonDoc()) —
|
|
* même principe repris ici avec sa propre clé (`ESPACE_CLE_SECRETE`) :
|
|
*
|
|
* - Dossier "tenant" (une base de travail, ex. MS-DEV) : HMAC-SHA256(clé
|
|
* secrète, host+base), tronqué. Déterministe (pas besoin de le stocker),
|
|
* mais infaisable à deviner sans la clé — contrairement à un simple
|
|
* SHA256, la présence d'une clé secrète rend une attaque par dictionnaire
|
|
* inopérante même en connaissant tous les noms de bases possibles.
|
|
* - Dossier "utilisateur" (une ligne MIR_Users) : jeton ALÉATOIRE
|
|
* (random_bytes), jamais dérivé d'un nom ou d'un numéro — rien à deviner,
|
|
* rien à casser. Généré une seule fois, à la volée, au premier besoin
|
|
* réel (même principe de création différée que creerSiteSiBesoin() dans
|
|
* mission_agent.php) puis conservé dans MIR_Users.MIR_Espace.
|
|
*
|
|
* Rappel de architecture (voir Réflexions stratégiques, section 21) : cette
|
|
* opacité de nom n'est qu'une défense en profondeur. La vraie protection est
|
|
* que RACINE_ESPACES vit hors de toute racine servie par Apache (volume
|
|
* Docker dédié, ajouté le 11 septembre 2026) — aucune URL ne peut jamais
|
|
* l'atteindre, quel que soit le nom des dossiers.
|
|
*/
|
|
|
|
const RACINE_ESPACES = '/var/www/espaces_utilisateurs';
|
|
|
|
function cheminTenant(string $host, string $baseNom): string
|
|
{
|
|
$cle = getenv('ESPACE_CLE_SECRETE');
|
|
if (!$cle) {
|
|
error_log('ASPIC espace_utilisateur : ESPACE_CLE_SECRETE non configurée');
|
|
$cle = 'repli-non-securise'; // ne devrait jamais arriver en pratique — voir docker-compose.yml
|
|
}
|
|
return substr(hash_hmac('sha256', "$host|$baseNom", $cle), 0, 16);
|
|
}
|
|
|
|
/**
|
|
* Jeton opaque de l'utilisateur (ligne MIR_Users) — lit MIR_Espace, le
|
|
* génère et le persiste au besoin (jamais recalculé une fois posé, pour ne
|
|
* jamais faire "bouger" un dossier déjà créé sur disque).
|
|
*
|
|
* Clé = MIR_Email, jamais MIR_Code : MIR_Code n'est PAS unique dans
|
|
* MIR_Users (ex. "JMP" partagé par les lignes "JMP Dev"/"JMP Tests", deux
|
|
* comptes distincts du même humain sur deux bases différentes) — seul
|
|
* MIR_Email identifie une ligne sans ambiguïté (même colonne que la
|
|
* vérification de mot de passe, voir aspic.php).
|
|
*/
|
|
function jetonUtilisateur(PDO $pdoRouter, string $mirEmail): string
|
|
{
|
|
$stmt = $pdoRouter->prepare('SELECT MIR_Espace FROM MIR_Users WHERE MIR_Email = ? LIMIT 1');
|
|
$stmt->execute([$mirEmail]);
|
|
$ligne = $stmt->fetch();
|
|
if ($ligne && $ligne['MIR_Espace']) {
|
|
return $ligne['MIR_Espace'];
|
|
}
|
|
$jeton = bin2hex(random_bytes(8)); // 16 caractères hexadécimaux, aléatoires, jamais dérivés d'un nom
|
|
$pdoRouter->prepare('UPDATE MIR_Users SET MIR_Espace = ? WHERE MIR_Email = ?')
|
|
->execute([$jeton, $mirEmail]);
|
|
return $jeton;
|
|
}
|
|
|
|
/**
|
|
* Résout (et crée si besoin) le dossier physique complet d'un utilisateur.
|
|
* Retourne le chemin absolu sur le disque du conteneur.
|
|
*/
|
|
function resoudreEspaceUtilisateur(PDO $pdoRouter, string $mirEmail, string $host, string $baseNom): string
|
|
{
|
|
$dossierRelatif = cheminTenant($host, $baseNom) . '/' . jetonUtilisateur($pdoRouter, $mirEmail);
|
|
$chemin = RACINE_ESPACES . '/' . $dossierRelatif;
|
|
if (!is_dir($chemin)) {
|
|
@mkdir($chemin, 0777, true);
|
|
@chmod($chemin, 0777);
|
|
}
|
|
return $chemin;
|
|
}
|