Code admin.php

Depuis votre terminal, connectez-vous a votre Raspberry PI et rentrez la commande suivante pour créer le fichier admin.php.

sudo nano /var/www/html/admin.php

Copier le code suivant et coller le dans le fichier qui vient de s'ouvrir.

<?php
date_default_timezone_set('Europe/Paris');

session_start();

// --- CONFIGURATION CRITIQUE (Doit correspondre à index.php) ---
// PIN sécurisé : Hash qui est COMPATIBLE avec votre fonction SHA-256 en pur JavaScript.
// Remplacer par le hash de votre code pin, valeur actuel '1234'
define('PIN_HASH_STORAGE', 'Remplacer ce texte par le hash de votre code pin');
const MAX_ATTEMPTS = 3; 
const BLACKLIST_FILE = '/var/www/html/data/admin_blacklist.json';
const LOG_FILE = '/var/log/camera_status.log'; 
// --------------------------------------------------------------

// >> FONCTIONS ET LOGIQUE DE SÉCURITÉ PHP <<

$client_ip = $_SERVER['REMOTE_ADDR'];

function get_blacklist() {
    if (file_exists(BLACKLIST_FILE)) {
        $data = file_get_contents(BLACKLIST_FILE);
        return json_decode($data, true) ?: [];
    }
    return [];
}

function save_blacklist($blacklist) {
    file_put_contents(BLACKLIST_FILE, json_encode($blacklist, JSON_PRETTY_PRINT));
}

function is_ip_blacklisted($ip) {
    $blacklist = get_blacklist();
    return isset($blacklist[$ip]);
}

if (!isset($_SESSION['pin_attempts_admin'])) {
    $_SESSION['pin_attempts_admin'] = 0;
}

// Vérifie si l'IP est déjà bloquée (liste noire) ou si la limite de tentatives en session est dépassée.
$is_ip_blocked = is_ip_blacklisted($client_ip);
$attempts_exceeded = ($_SESSION['pin_attempts_admin'] >= MAX_ATTEMPTS);

if ($is_ip_blocked || $attempts_exceeded) {
    if (!$is_ip_blocked && $attempts_exceeded) {
        // Blocage de l'IP si la limite de session est atteinte
        $blacklist = get_blacklist();
        $timestamp = date('Y-m-d H:i:s');
        $blacklist[$client_ip] = ['blocked_time' => $timestamp, 'reason' => 'Tentatives de PIN dépassées (ADMIN)'];
        save_blacklist($blacklist);
        
        session_destroy();
    }
    
    // Affiche l'erreur 403 et coupe l'accès
    header('HTTP/1.0 403 Forbidden');
    echo '<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><title>Accès Refusé</title><style>body { font-family: sans-serif; text-align: center; padding-top: 50px; background-color: #fdd; color: #800; }</style></head><body><h1>❌ ACCÈS TEMPORAIREMENT BLOQUÉ</h1><p>Votre adresse IP a été bloquée pour raisons de sécurité suite à trop de tentatives de connexion échouées sur la page d\'administration.</p></body></html>';
    exit;
}


// --- GESTION DES ACTIONS (Déblocage) ---

// Le contenu principal est affiché UNIQUEMENT si l'utilisateur est connecté (PIN entré correctement)
$is_admin_logged_in = isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true;


if ($is_admin_logged_in) {
    // Logique de gestion du déblocage d'IP (seulement si connecté)
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['unblock_ip'])) {
        $ip_to_unblock = filter_var($_POST['unblock_ip'], FILTER_VALIDATE_IP);
        
        if ($ip_to_unblock) {
            $blacklist = get_blacklist();
            if (isset($blacklist[$ip_to_unblock])) {
                unset($blacklist[$ip_to_unblock]);
                save_blacklist($blacklist);
                
                $timestamp = date('Y-m-d H:i:s');
                $log_message = sprintf("[%s] [SECURITY] IP Unblocked: %s by Admin IP: %s\n", $timestamp, $ip_to_unblock, $client_ip);
                file_put_contents(LOG_FILE, $log_message, FILE_APPEND | LOCK_EX);
                
                $_SESSION['admin_message'] = "L'IP $ip_to_unblock a été débloquée.";
            } else {
                $_SESSION['admin_message'] = "Erreur: L'IP $ip_to_unblock n'était pas bloquée.";
            }
        } else {
            $_SESSION['admin_message'] = "Erreur: Format d'IP invalide.";
        }
        header('Location: admin.php');
        exit;
    }
}
// Récupère la liste des IP pour l'affichage (si connecté)
$current_blacklist = $is_admin_logged_in ? get_blacklist() : [];

$admin_message = '';
if (isset($_SESSION['admin_message'])) {
    $admin_message = $_SESSION['admin_message'];
    unset($_SESSION['admin_message']);
}
?>

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Administration Blocage IP</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background-color: #f0f0f5; color: #333; margin: 0; padding: 20px; text-align: center; }
        .container { max-width: 600px; margin: 0 auto; background-color: #fff; padding: 20px; border-radius: 12px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); text-align: left; }
        h1 { color: #1a1a1a; font-size: 24px; margin-bottom: 20px; text-align: center; }
        .ip-list { list-style: none; padding: 0; }
        .ip-list li { display: flex; justify-content: space-between; align-items: center; padding: 10px; border-bottom: 1px solid #eee; }
        .ip-list li:last-child { border-bottom: none; }
        .ip-info { flex-grow: 1; }
        .ip-address { font-weight: bold; }
        .unblock-btn { background-color: #ff3b30; color: white; border: none; padding: 8px 12px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
        .unblock-btn:hover { background-color: #cc2e24; }
        .message { padding: 10px; margin-bottom: 20px; border-radius: 6px; font-weight: bold; }
        .info { background-color: #e6f7ff; color: #007aff; border: 1px solid #007aff; }
        
        /* Styles pour le PIN */
        .pin-container { background: white; padding: 30px; border-radius: 15px; text-align: center; width: 80%; max-width: 300px; margin: 50px auto; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); }
        .pin-input { width: 100%; padding: 10px; font-size: 20px; margin: 10px 0 20px; text-align: center; letter-spacing: 5px; }
    </style>
</head>
<body>

<?php if (!$is_admin_logged_in): ?>
    <div class="pin-container">
        <h1>Accès Administration Sécurisé</h1>
        <h3>Entrez votre code PIN</h3>
        <input type="password" id="pinInput" class="pin-input" maxlength="4" inputmode="numeric" oninput="checkPin();">
        <p style="font-size: 14px; color: #555;">Tentatives restantes: <span id="attempts_left_admin"><?php echo MAX_ATTEMPTS - $_SESSION['pin_attempts_admin']; ?></span></p>
        <p id="pinMessage" style="color: red;"></p>
        <p style="margin-top: 30px;"><a href="index.php" style="color:#007aff; text-decoration: none;">&larr; Retour à l'accueil</a></p>
    </div>

<?php else: ?>
    <div class="container">
        <h1>Administration de la Liste Noire (IP: <?php echo htmlspecialchars($client_ip); ?>)</h1>
        
        <?php if ($admin_message): ?>
            <div class="message info">
                <?php echo htmlspecialchars($admin_message); ?>
            </div>
        <?php endif; ?>

        <h2>Adresses IP Bloquées (<?php echo count($current_blacklist); ?>)</h2>

        <?php if (empty($current_blacklist)): ?>
            <p>Aucune adresse IP n'est actuellement bloquée.</p>
        <?php else: ?>
            <ul class="ip-list">
                <?php foreach ($current_blacklist as $ip => $data): ?>
                    <li>
                        <div class="ip-info">
                            <span class="ip-address"><?php echo htmlspecialchars($ip); ?></span>
                            <br>
                            <small>Bloqué le: <?php echo htmlspecialchars($data['blocked_time'] ?? 'N/A'); ?> (Raison: <?php echo htmlspecialchars($data['reason'] ?? 'Inconnue'); ?>)</small>
                        </div>
                        <form method="POST" action="admin.php">
                            <input type="hidden" name="unblock_ip" value="<?php echo htmlspecialchars($ip); ?>">
                            <button type="submit" class="unblock-btn">Débloquer</button>
                        </form>
                    </li>
                <?php endforeach; ?>
            </ul>
        <?php endif; ?>
        
        <p style="text-align: center; margin-top: 30px;"><a href="index.php" style="color:#007aff; text-decoration: none;">&larr; Retour à la page de contrôle</a></p>
    </div>
<?php endif; ?>


<script>
    // Récupération des constantes PHP
    const CORRECT_PIN_HASH = "<?php echo PIN_HASH_STORAGE; ?>"; 
    const is_admin_logged_in = <?php echo json_encode($is_admin_logged_in); ?>;
    
    // N'exécuter le script de PIN que si l'administrateur n'est pas déjà connecté
    if (!is_admin_logged_in) {
        
        // La fonction SHA-256 synchrone spécifique à votre projet (copiée de index.php)
        function sha256(str) {
            function rotateRight(n, count) {
                return (n >>> count) | (n << (32 - count));
            }
            function safeAdd(x, y) {
                const lsw = (x & 0xFFFF) + (y & 0xFFFF);
                const msw = (x >> 16) + (y >> 16) + (lsw >> 16); // Corrected safeAdd
                return (msw << 16) | (lsw & 0xFFFF);
            }

            const K = [
                0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
                0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
                0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
                0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
                0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
                0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
                0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
                0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
            ];
            
            let H = [
                0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
            ];

            const utf8 = unescape(encodeURIComponent(str));
            const w = [];
            let i;
            for (i = 0; i < utf8.length * 8; i += 8) {
                w[i >> 5] |= (utf8.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
            }

            w[i >> 5] |= 0x80 << (24 - i % 32);
            w[((i + 64) >>> 9 << 4) + 15] = i;

            for (let j = 0; j < w.length; j += 16) {
                const W = new Array(64);
                let a = H[0], b = H[1], c = H[2], d = H[3], e = H[4], f = H[5], g = H[6], h = H[7];

                for (let t = 0; t < 64; t++) {
                    if (t < 16) {
                        W[t] = w[j + t];
                    } else {
                        const s0 = rotateRight(W[t - 15], 7) ^ rotateRight(W[t - 15], 18) ^ (W[t - 15] >>> 3);
                        const s1 = rotateRight(W[t - 2], 17) ^ rotateRight(W[t - 2], 19) ^ (W[t - 2] >>> 10);
                        W[t] = safeAdd(safeAdd(safeAdd(W[t - 16], s0), W[t - 7]), s1);
                    }
                    
                    const S1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
                    const ch = (e & f) ^ ((~e) & g);
                    const temp1 = safeAdd(safeAdd(safeAdd(safeAdd(h, S1), ch), K[t]), W[t]);
                    const S0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
                    const maj = (a & b) ^ (a & c) ^ (b & c);
                    const temp2 = safeAdd(S0, maj);

                    h = g;
                    g = f;
                    f = e;
                    e = safeAdd(d, temp1);
                    d = c;
                    c = b;
                    b = a;
                    a = safeAdd(temp1, temp2);
                }

                H[0] = safeAdd(a, H[0]);
                H[1] = safeAdd(b, H[1]);
                H[2] = safeAdd(c, H[2]);
                H[3] = safeAdd(d, H[3]);
                H[4] = safeAdd(e, H[4]);
                H[5] = safeAdd(f, H[5]);
                H[6] = safeAdd(g, H[6]);
                H[7] = safeAdd(h, H[7]);
            }
            
            let result = '';
            for (let t = 0; t < H.length; t++) {
                result += H[t].toString(16).padStart(8, '0');
            }
            return result.replace(/[^0-9a-f]/gi, '').toLowerCase(); 
        }

        function checkPin() {
            const pinInput = document.getElementById('pinInput');
            const pin = pinInput.value;
            const messageElement = document.getElementById('pinMessage');
            
            if (pin.length === 4) { 
                messageElement.textContent = "Vérification...";
                
                const hashedInput = sha256(pin); 
                
                if (hashedInput === CORRECT_PIN_HASH) {
                    messageElement.textContent = "Connexion OK. Redirection...";
                    // Succès : Appeler un endpoint PHP qui définit la session 'admin_logged_in'
                    fetch('admin_login.php')
                        .then(response => {
                             if (!response.ok) throw new Error("Erreur de connexion.");
                             return response.json();
                        })
                        .then(data => {
                            if (data.status === 'success') {
                                window.location.reload(); // Recharger la page pour afficher le panneau
                            } else {
                                messageElement.textContent = "Erreur interne de session.";
                            }
                        })
                        .catch(error => {
                             messageElement.textContent = "Erreur de communication avec le serveur (admin_login.php).";
                             console.error(error);
                        });
                        
                } else {
                    // PIN incorrect : Appel au PHP pour incrémenter le compteur de tentatives (pour la page admin)
                    fetch('pin_failed_admin.php')
                        .then(response => {
                            if (!response.ok) throw new Error("Erreur serveur lors de la tentative échouée.");
                            return response.json();
                        })
                        .then(data => {
                            if (data.status === 'blocked') {
                                window.location.reload(); 
                            } else {
                                messageElement.textContent = "Code PIN incorrect.";
                                pinInput.value = '';
                                document.getElementById('attempts_left_admin').textContent = data.attempts_left;
                            }
                        })
                        .catch(error => {
                            messageElement.textContent = "Erreur de communication avec le serveur (pin_failed_admin.php).";
                            console.error(error);
                        });
                }
            }
        }
    }
</script>
</body>
</html>

 

- Vous devez remplacer la valeur de la variable " PIN_HASH_STORAGE " par le Hash de votre code pin. Pour connaitre la valeur du hash utiliser cette commande en remplaçant "1234" par votre code pin.

echo -n "1234" | sha256sum

- Le résultat est "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"