From 994071243fc80990cf09e820b671006e9bd31c76 Mon Sep 17 00:00:00 2001 From: Gab <24553253+gabrix73@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:04:30 +0200 Subject: Separate active YAMN code from Katzenpost PoC --- index.php | 392 ++++++++++++++++++++++---------------------------------------- 1 file changed, 141 insertions(+), 251 deletions(-) (limited to 'index.php') diff --git a/index.php b/index.php index 6b112c8..64c47d6 100644 --- a/index.php +++ b/index.php @@ -1,6 +1,6 @@ forceUpdate()) { + throw new Exception('Remailer list update failed. The previous list was kept where possible.'); + } + + $_SESSION['flash_message'] = 'Remailer list and public keyring updated successfully.'; + $_SESSION['flash_type'] = 'success'; + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + header('Location: ' . $_SERVER['PHP_SELF']); + exit; + } + // Get and sanitize form data with additional validation $entryRemailer = isset($_POST['entry_remailer']) ? filter_var($_POST['entry_remailer'], FILTER_SANITIZE_STRING) : ''; $middleRemailer = isset($_POST['middle_remailer']) ? filter_var($_POST['middle_remailer'], FILTER_SANITIZE_STRING) : ''; @@ -257,15 +273,22 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') { throw new Exception("Number of copies must be between 1 and 3."); } - // Validate required fields - if (empty($to)) { - throw new Exception("Recipient (To) is required."); - } - if (empty($from)) { throw new Exception("Sender (From) is required."); } + $messageKind = trim($newsgroups) === '' ? 'email' : 'usenet'; + if ($messageKind === 'email' && empty($to)) { + throw new Exception("Email recipient is required when Newsgroup is empty."); + } + + if ($messageKind === 'usenet') { + $to = yamnConfig('YAMN_USENET_GATEWAY', 'mail2news@mail2news.tcpreset.net'); + if (!filter_var($to, FILTER_VALIDATE_EMAIL)) { + throw new Exception("Usenet gateway is not configured correctly."); + } + } + // Validate remailer chain if (empty($entryRemailer) || empty($middleRemailer) || empty($exitRemailer)) { throw new Exception("All three remailers must be specified."); @@ -276,125 +299,48 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') { $resolvedMiddle = resolveRemailer($middleRemailer, $middleRemailers); $resolvedExit = resolveRemailer($exitRemailer, $exitRemailers); - // Build remailer chain with resolved names - $chain = "$resolvedEntry,$resolvedMiddle,$resolvedExit"; - - // Log the resolved chain for debugging - error_log("Resolved remailer chain: $chain (from: $entryRemailer,$middleRemailer,$exitRemailer)"); - - // Build message headers - $headers = "Content-Type: text/plain; charset=utf-8\n"; - $headers .= "Content-Transfer-Encoding: 8bit\n"; - $headers .= "MIME-Version: 1.0\n"; - - if (!empty($references)) { - $headers .= "References: $references\n"; + $encoded = encodeYamnMessage([ + 'kind' => $messageKind, + 'entry' => $resolvedEntry, + 'chain' => [$resolvedEntry, $resolvedMiddle, $resolvedExit], + 'from' => $from, + 'reply_to' => $replyTo, + 'to' => $to, + 'subject' => $subject, + 'newsgroup' => $newsgroups, + 'body' => $data, + 'references' => $references, + ]); + if (!$encoded['success']) { + throw new Exception($encoded['error'] ?? 'YAMN encoding failed'); } - - // Build complete message - $messageContent = $headers . "From: $from\n"; - - if (!empty($replyTo)) { - $messageContent .= "Reply-To: $replyTo\n"; - } - - $messageContent .= "To: $to\nSubject: $subject\n"; - - if (!empty($newsgroups)) { - $messageContent .= "Newsgroups: $newsgroups\n"; - } - - $messageContent .= "\n$data"; - - // Verify YAMN executable exists - $yamnPath = '/opt/yamn-master/yamn'; - if (!file_exists($yamnPath)) { - throw new Exception("YAMN executable not found at: $yamnPath"); - } - - if (!is_executable($yamnPath)) { - throw new Exception("YAMN executable is not executable. Check permissions."); - } - - // Verify YAMN config file exists - $yamnConfig = '/opt/yamn-master/yamn.yml'; - if (!file_exists($yamnConfig)) { - throw new Exception("YAMN config file not found at: $yamnConfig"); - } - - // Ensure temp directory exists and is writable - $tempDir = '/var/www/yamnweb'; - if (!is_dir($tempDir)) { - throw new Exception("Temp directory does not exist: $tempDir"); - } - - if (!is_writable($tempDir)) { - throw new Exception("Temp directory is not writable: $tempDir"); - } - - // Ensure Maildir exists (required by YAMN) - $maildirBase = '/var/www/yamnweb/Maildir'; - $maildirDirs = [ - $maildirBase, - $maildirBase . '/tmp', - $maildirBase . '/new', - $maildirBase . '/cur' - ]; - - foreach ($maildirDirs as $dir) { - if (!is_dir($dir)) { - if (!@mkdir($dir, 0755, true)) { - throw new Exception("Failed to create Maildir directory: $dir"); - } - error_log("Created Maildir directory: $dir"); - } - } - - // Write message to temp file (use single file as in original) - $tempFile = $tempDir . '/message.txt'; - $writeResult = @file_put_contents($tempFile, $messageContent); - - if ($writeResult === false) { - throw new Exception("Failed to write message to temporary file: $tempFile"); - } - - // Verify file was written - if (!file_exists($tempFile)) { - throw new Exception("Temp file was not created: $tempFile"); - } - - // Log to debug.log - $debugLog = '/var/www/yamnweb/debug.log'; - file_put_contents($debugLog, date('Y-m-d H:i:s') . " - Starting email send\n", FILE_APPEND); - file_put_contents($debugLog, "To: $to | Chain: $chain | Copies: $copies\n", FILE_APPEND); - - // Use sendYamnEmail() from tor_extension.php - if (function_exists('sendYamnEmail')) { - $result = sendYamnEmail($chain, $copies, $tempFile, true); - - // Log result - file_put_contents($debugLog, date('Y-m-d H:i:s') . " - Result: " . ($result['success'] ? 'SUCCESS' : 'FAILED') . "\n", FILE_APPEND); - - // Clean up - @unlink($tempFile); - - if ($result['success']) { - // Success - save message in session and redirect (PRG pattern) - $_SESSION['flash_message'] = "✓ Message sent successfully via YAMN network ($copies " . ($copies > 1 ? "copies" : "copy") . ")"; + $responseFinished = false; + $onHandoff = null; + if (function_exists('fastcgi_finish_request')) { + $onHandoff = static function () use (&$responseFinished): void { + ignore_user_abort(true); + $_SESSION['flash_message'] = 'Message handed to the local Nym transport. The sender is completing delivery in the background; YAMN queues may take several hours, and this confirmation does not mean the message has been published or delivered yet.'; $_SESSION['flash_type'] = 'success'; - - // Regenerate CSRF token after successful submission $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); - - // Redirect to prevent form resubmission on page reload + session_write_close(); header('Location: ' . $_SERVER['PHP_SELF']); - exit; - } else { - throw new Exception("YAMN send failed. Check debug.log for details."); - } - } else { - throw new Exception("sendYamnEmail() function not found. Check tor_extension.php"); + fastcgi_finish_request(); + $responseFinished = true; + }; + } + + $result = sendNymEnvelope($encoded['envelope'], 1, $encoded['entry_address'], $onHandoff); + if ($responseFinished) { + exit; } + if (!$result['success']) { + throw new Exception($result['error'] ?? 'Nym submission failed'); + } + $_SESSION['flash_message'] = 'Message accepted by the Nym transport. Delivery through the YAMN queues may take several hours; this confirmation does not mean the message has been published or delivered yet.'; + $_SESSION['flash_type'] = 'success'; + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + header('Location: ' . $_SERVER['PHP_SELF']); + exit; } catch (Exception $e) { // Save error in session and redirect (PRG pattern for errors too) $_SESSION['flash_message'] = "✗ Error: " . $e->getMessage(); @@ -427,11 +373,11 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') { } ?> - +
-