downloadRemailers(); // Reload after download $entryRemailers = getRemailers('entry'); $middleRemailers = getRemailers('middle'); $exitRemailers = getRemailers('exit'); } catch (Exception $e) { error_log("Failed to download remailers: " . $e->getMessage()); } } $message = ''; $messageType = ''; // Check for flash messages from previous redirect (PRG pattern) if (isset($_SESSION['flash_message'])) { $message = $_SESSION['flash_message']; $messageType = isset($_SESSION['flash_type']) ? $_SESSION['flash_type'] : 'info'; // Clear flash messages after displaying unset($_SESSION['flash_message']); unset($_SESSION['flash_type']); } // Handle form submission if ($_SERVER['REQUEST_METHOD'] == 'POST') { // CSRF validation - IMPROVED with better error handling if (!isset($_POST['csrf_token'])) { // Save error in session and redirect $_SESSION['flash_message'] = "Security token missing. Please reload the page and try again."; $_SESSION['flash_type'] = 'error'; header('Location: ' . $_SERVER['PHP_SELF']); exit; } elseif ($_POST['csrf_token'] !== $currentCsrfToken) { // DEBUG: Log the mismatch for troubleshooting error_log("CSRF Mismatch - POST: " . substr($_POST['csrf_token'], 0, 10) . "... SESSION: " . substr($currentCsrfToken, 0, 10) . "..."); // Save error in session and redirect $_SESSION['flash_message'] = "Security token mismatch. Please try submitting again."; $_SESSION['flash_type'] = 'error'; header('Location: ' . $_SERVER['PHP_SELF']); exit; } else { try { // 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) : ''; $exitRemailer = isset($_POST['exit_remailer']) ? filter_var($_POST['exit_remailer'], FILTER_SANITIZE_STRING) : ''; $from = isset($_POST['from']) ? filter_var($_POST['from'], FILTER_SANITIZE_STRING) : ''; $replyTo = isset($_POST['reply_to']) ? filter_var($_POST['reply_to'], FILTER_SANITIZE_STRING) : ''; $to = isset($_POST['to']) ? filter_var($_POST['to'], FILTER_SANITIZE_EMAIL) : ''; $subject = isset($_POST['subject']) ? filter_var($_POST['subject'], FILTER_SANITIZE_STRING) : ''; $newsgroups = isset($_POST['newsgroups']) ? filter_var($_POST['newsgroups'], FILTER_SANITIZE_STRING) : ''; $references = isset($_POST['references']) ? filter_var($_POST['references'], FILTER_SANITIZE_STRING) : ''; $data = isset($_POST['data']) ? $_POST['data'] : ''; // Keep original formatting $copies = isset($_POST['copies']) ? intval($_POST['copies']) : 1; // Validate copies if ($copies < 1 || $copies > 3) { 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."); } // Validate remailer chain if (empty($entryRemailer) || empty($middleRemailer) || empty($exitRemailer)) { throw new Exception("All three remailers must be specified."); } // Resolve asterisks (*) to actual random remailers $resolvedEntry = resolveRemailer($entryRemailer, $entryRemailers); $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"; } // 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") . ")"; $_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 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"); } } catch (Exception $e) { // Save error in session and redirect (PRG pattern for errors too) $_SESSION['flash_message'] = "✗ Error: " . $e->getMessage(); $_SESSION['flash_type'] = 'error'; error_log("YAMN submission error: " . $e->getMessage() . "\nStack: " . $e->getTraceAsString()); // Redirect to prevent form resubmission header('Location: ' . $_SERVER['PHP_SELF']); exit; } catch (Error $e) { // Catch PHP 7+ Error class (for fatal errors) $_SESSION['flash_message'] = "✗ Fatal Error: " . $e->getMessage(); $_SESSION['flash_type'] = 'error'; error_log("YAMN fatal error: " . $e->getMessage() . "\nStack: " . $e->getTraceAsString()); // Redirect to prevent form resubmission header('Location: ' . $_SERVER['PHP_SELF']); exit; } catch (Throwable $e) { // Catch everything else $_SESSION['flash_message'] = "✗ Unexpected error: " . $e->getMessage(); $_SESSION['flash_type'] = 'error'; error_log("YAMN unexpected error: " . $e->getMessage()); // Redirect to prevent form resubmission header('Location: ' . $_SERVER['PHP_SELF']); exit; } } } ?> YAMN Web Interface

⚡ YAMN WEB INTERFACE ⚡

Tor before Yamn Remailer Network
DEBUG INFO: Session ID: ...
CSRF Token: ...
PHP Version:
Session Save Path:
Cookie Params:
Security Features Active:
Multiple copies increase reliability through redundancy