diff --git a/encoder/firmware.php b/encoder/firmware.php index 7d5759f..7a1a26a 100755 --- a/encoder/firmware.php +++ b/encoder/firmware.php @@ -347,13 +347,17 @@ EwIDAQAB 'firmware.json', ]; + /* 1. Remove existing config files */ foreach ($jsonFiles as $json) { if (file_exists($json)) { unlink($json); } } - $tmpZip = sys_get_temp_dir() . '/restore.zip'; + /* 2. Validate upload */ + if (!isset($_FILES['shree_bhattji_encoder'])) { + die('No file uploaded'); + } $upload = $_FILES['shree_bhattji_encoder']; @@ -361,42 +365,71 @@ EwIDAQAB die('Upload failed'); } - if (pathinfo($upload['name'], PATHINFO_EXTENSION) !== 'bin') { + if (strtolower(pathinfo($upload['name'], PATHINFO_EXTENSION)) !== 'bin') { die('Invalid file type'); } + /* 3. Load private key */ $privateKeyPem = file_get_contents('/var/www/backup_private.pem'); - if (!$privateKeyPem) { + if ($privateKeyPem === false) { die('Private key not found'); } $privateKey = openssl_pkey_get_private($privateKeyPem); - if (!$privateKey) { + if ($privateKey === false) { die('Invalid private key'); } + /* 4. Read binary backup */ $payloadRaw = file_get_contents($upload['tmp_name']); - $payload = json_decode($payloadRaw, true); - - if ( - !is_array($payload) - || !isset($payload['key'], $payload['iv'], $payload['data']) - ) { - die('Invalid backup file format'); + if ($payloadRaw === false) { + die('Failed to read backup file'); } - $encryptedKey = base64_decode($payload['key'], true); - $iv = base64_decode($payload['iv'], true); - $encryptedData = base64_decode($payload['data'], true); + $offset = 0; - if ($encryptedKey === false || $iv === false || $encryptedData === false) { - die('Corrupt backup data'); + /* 5. Read RSA key length (4 bytes, big-endian) */ + if (strlen($payloadRaw) < 4) { + die('Corrupt backup file'); } + $keyLen = unpack('N', substr($payloadRaw, 0, 4))[1]; + $offset += 4; + + if ($keyLen <= 0 || $keyLen > 512) { + die('Invalid encrypted key length'); + } + + /* 6. Read RSA-encrypted AES key */ + $encryptedKey = substr($payloadRaw, $offset, $keyLen); + if (strlen($encryptedKey) !== $keyLen) { + die('Corrupt encrypted key'); + } + $offset += $keyLen; + + /* 7. Read IV */ + $iv = substr($payloadRaw, $offset, 16); + if (strlen($iv) !== 16) { + die('Invalid IV'); + } + $offset += 16; + + /* 8. Remaining data = AES-encrypted ZIP */ + $encryptedData = substr($payloadRaw, $offset); + if ($encryptedData === '') { + die('Missing encrypted payload'); + } + + /* 9. Decrypt AES key */ if (!openssl_private_decrypt($encryptedKey, $aesKey, $privateKey)) { die('Key mismatch or wrong private key'); } + if (strlen($aesKey) !== 32) { + die('Invalid AES key length'); + } + + /* 10. Decrypt ZIP */ $zipBinary = openssl_decrypt( $encryptedData, 'AES-256-CBC', @@ -408,18 +441,32 @@ EwIDAQAB if ($zipBinary === false) { die('Failed to decrypt data'); } - $tmpZip = sys_get_temp_dir() . '/restore_' . uniqid() . '.zip'; + + /* 11. Write ZIP to temp file */ + $tmpZip = sys_get_temp_dir() . '/restore_' . uniqid('', true) . '.zip'; file_put_contents($tmpZip, $zipBinary); + /* 12. Extract ZIP safely */ $zip = new ZipArchive(); if ($zip->open($tmpZip) !== true) { unlink($tmpZip); die('Invalid ZIP archive'); } - $zip->extractTo(__DIR__); // overwrites existing JSON + $restoreDir = __DIR__ . '/restore_tmp'; + @mkdir($restoreDir, 0700, true); + $zip->extractTo($restoreDir); $zip->close(); + /* 13. Restore only expected JSON files */ + foreach ($jsonFiles as $file) { + $src = $restoreDir . '/' . $file; + if (file_exists($src)) { + rename($src, __DIR__ . '/' . $file); + } + } + + /* 14. Cleanup */ unlink($tmpZip); update_service("display"); update_service("rtmp0"); diff --git a/install.sh b/install.sh index b1337a2..875929d 100755 --- a/install.sh +++ b/install.sh @@ -180,6 +180,52 @@ RestartSec=30 WantedBy=multi-user.target EOL +cat > /etc/systemd/system/drm-key.service<< 'EOL' +[Unit] +Description=HLS Key Generator and Poster +After=network-online.target +Wants=network-online.target + +[Service] +Type=key genrator +User=root +Group=root +ExecStart=/var/www/key.sh +WorkingDirectory=/var/www +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target +EOL + +cat > /var/www/key.sh<< 'EOL' +#!/bin/bash +set -e + +# ===== CONFIG ===== +STREAM_ID="strem_id_strem_id_strem_id" +KEY_FILE="/var/www/scrambler.key" +# ================== + +# Timestamp +TIMESTAMP=$(date +%s) + +# Dynamic POST field name +KEY_FIELD="${STREAM_ID}_${TIMESTAMP}" + +# Generate secure random 16-byte key (binary) +openssl rand 16 > "$KEY_FILE" + +# Convert binary key to hex for HTTP transport +KEY_HEX=$(xxd -p "$KEY_FILE" | tr -d '\n') + +curl --fail --silent --show-error \ + -X POST "$post_url_post_url_post_url" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + --data "stream_id=${STREAM_ID}&${KEY_FIELD}=${KEY_HEX}" +EOL + # graph monitor setup cat > /etc/systemd/system/system-monitor.service<< 'EOL' [Unit] @@ -408,8 +454,6 @@ sudo chown -R www-data:www-data /var/www sudo systemctl daemon-reload sudo chmod 444 /sys/class/dmi/id/product_uuid -sudo systemctl disable systemd-networkd-wait-online.service -sudo systemctl mask systemd-networkd-wait-online.service sudo ufw default allow outgoing sudo ufw default deny incoming diff --git a/setup.sh b/setup.sh index 87c1327..122a526 100644 --- a/setup.sh +++ b/setup.sh @@ -148,7 +148,8 @@ RestartSec=30 WantedBy=multi-user.target EOL - +sudo systemctl unmask systemd-networkd-wait-online.service +sudo systemctl enable systemd-networkd-wait-online.service sudo systemctl daemon-reload sudo systemctl restart nginx sudo a2enmod ssl