summaryrefslogtreecommitdiffstats
path: root/tor_extension.php
blob: 4c18f9f21fc720da6fdf264edc81a014c7a42547 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<?php
/**
 * Tor Extension for YAMN Web Interface
 * Handles Tor integration for anonymous remailer network
 */

// Constants
define('YAMN_PATH', '/opt/yamn-master/yamn');
define('YAMN_CONFIG', '/opt/yamn-master/yamn.cfg');
define('TOR_PROXY', '127.0.0.1:9050');
define('TOR_CONFIG_FILE', '/var/www/yamnweb/tor_config.ini');
define('TORSOCKS_PATH', 'torsocks');

// SMTP Onion Relays - Primary and Fallback
define('SMTP_RELAYS', [
    [
        'host' => '4uwpi53u524xdphjw2dv5kywsxmyjxtk4facb76jgl3sc3nda3sz4fqd.onion',
        'port' => 25,
        'name' => 'Primary Onion SMTP'
    ],
    [
        'host' => 'xilb7y4kj6u6qfo45o3yk2kilfv54ffukzei3puonuqlncy7cn2afwyd.onion',
        'port' => 25,
        'name' => 'Fallback Onion SMTP'
    ]
]);

/**
 * Debug logger function
 *
 * @param string $message Message to log
 * @param bool $include_timestamp Whether to include timestamp
 * @return void
 */
function logDebug($message, $include_timestamp = true) {
    $log_file = '/var/www/yamnweb/debug.log';
    $log_entry = ($include_timestamp ? date('Y-m-d H:i:s') . " - " : "") . $message . "\n";
    file_put_contents($log_file, $log_entry, FILE_APPEND);
}

/**
 * Check if Tor is available on the system
 *
 * @return bool True if Tor service is available
 */
function isTorAvailable() {
    logDebug("Checking if Tor is available...");

    // Check if torsocks is installed
    $torsocks_check = shell_exec('which torsocks 2>&1');
    if (empty($torsocks_check) || strpos($torsocks_check, 'no torsocks') !== false) {
        logDebug("WARNING: torsocks not found in PATH. Tor routing may not work correctly.");
    } else {
        logDebug("torsocks found: " . trim($torsocks_check));
    }

    // Check if Tor SOCKS proxy is listening
    $connection = @fsockopen('127.0.0.1', 9050, $errno, $errstr, 1);
    if (is_resource($connection)) {
        fclose($connection);
        logDebug("Tor is available: SOCKS proxy connection successful");
        return true;
    }

    logDebug("SOCKS proxy connection failed: $errno - $errstr");

    // Alternative: Check if Tor service is running
    $tor_running = shell_exec('pgrep -f "tor" | wc -l');
    if (intval($tor_running) > 0) {
        logDebug("Tor is available: Tor process is running");
        return true;
    }

    logDebug("Tor is NOT available: No Tor process found");
    return false;
}

/**
 * Check if an email address belongs to an .onion domain
 *
 * @param string $email The email address to check
 * @return bool True if the email is for an .onion domain
 */
function isOnionEmail($email) {
    // Extract domain from email address
    if (preg_match('/@([^>]+)/', $email, $matches)) {
        $domain = $matches[1];
        $is_onion = (strpos($domain, '.onion') !== false);
        logDebug("Email domain check: $domain - " . ($is_onion ? "is .onion" : "is NOT .onion"));
        return $is_onion;
    }
    logDebug("No domain found in email: $email");
    return false;
}

/**
 * Determine if Tor should be used for the current email
 *
 * @param string $to The recipient email address
 * @return bool True if Tor should be used
 */
function shouldUseTor($to) {
    logDebug("Checking if Tor should be used for recipient: $to");

    // Use Tor if the destination is an .onion address
    if (isOnionEmail($to)) {
        logDebug("Tor will be used: .onion address detected");
        return true;
    }

    // Use Tor if forced by configuration file
    if (file_exists(TOR_CONFIG_FILE)) {
        logDebug("Config file exists: " . TOR_CONFIG_FILE);
        $config = parse_ini_file(TOR_CONFIG_FILE, true);
        if (isset($config['tor']) && isset($config['tor']['force_tor'])) {
            $force_tor = ($config['tor']['force_tor'] === 'true' || $config['tor']['force_tor'] === '1');
            logDebug("Config file force_tor setting: " . ($force_tor ? "true" : "false"));
            return $force_tor;
        }
    }

    // Check environment variables
    $force_tor_env = getenv('YAMN_TOR_FORCE');
    if ($force_tor_env) {
        $result = ($force_tor_env === 'true' || $force_tor_env === '1');
        logDebug("Environment variable YAMN_TOR_FORCE: " . ($result ? "true" : "false"));
        return $result;
    }

    logDebug("Tor will NOT be used: No .onion address or force settings");
    return false;
}

/**
 * Configure Tor environment settings for YAMN
 *
 * @param bool $useTor Whether to force Tor usage
 * @return void
 */
function configureTorForYamn($useTor = false) {
    if ($useTor) {
        logDebug("Configuring Tor environment variables");

        // Set SOCKS proxy environment variables
        putenv("SOCKS_PROXY=" . TOR_PROXY);
        putenv("ALL_PROXY=socks5://" . TOR_PROXY);
        putenv("socks_proxy=" . TOR_PROXY);
        putenv("all_proxy=socks5://" . TOR_PROXY);
        putenv("YAMN_USE_TOR=1");
        putenv("YAMN_TOR_ENABLED=true");
        putenv("YAMN_TOR_FORCE=true");

        logDebug("Tor environment configured with proxy: " . TOR_PROXY);
    } else {
        logDebug("Clearing Tor environment variables");

        // Clear environment variables when not using Tor
        putenv("SOCKS_PROXY=");
        putenv("ALL_PROXY=");
        putenv("socks_proxy=");
        putenv("all_proxy=");
        putenv("YAMN_USE_TOR=0");
        putenv("YAMN_TOR_ENABLED=false");
        putenv("YAMN_TOR_FORCE=false");
    }
}

/**
 * Test SMTP relay connectivity through Tor
 *
 * @param string $host SMTP relay hostname
 * @param int $port SMTP port
 * @return bool True if relay is reachable
 */
function testSmtpRelay($host, $port) {
    logDebug("Testing SMTP relay: $host:$port");

    // Use torsocks to test connection through Tor
    $command = "timeout 10 torsocks nc -zv $host $port 2>&1";
    exec($command, $output, $return_var);

    $success = ($return_var == 0);
    logDebug("SMTP relay test result: " . ($success ? "SUCCESS" : "FAILED"));
    logDebug("Test output: " . implode(" ", $output));

    return $success;
}

/**
 * Update YAMN config with specific SMTP relay
 * VERSIONE DISABILITATA - Non modifica il file, usa configurazione statica
 *
 * @param string $host SMTP relay hostname
 * @param int $port SMTP port
 * @return bool True if update successful
 */
function updateYamnConfig($host, $port) {
    logDebug("Config update DISABLED - using static configuration");
    logDebug("Requested relay: $host:$port (will be ignored, using config file as-is)");

    // Verifica solo che il file esista
    if (!file_exists(YAMN_CONFIG)) {
        logDebug("ERROR: Config file not found: " . YAMN_CONFIG);
        return false;
    }

    logDebug("Config file exists, skipping dynamic update");
    return true;
}

/**
 * Send an email through YAMN with optional Tor routing and automatic fallback
 *
 * @param string $chain The remailer chain string (e.g., "entry,middle,exit")
 * @param int $copies Number of copies to send (1-3)
 * @param string $messageFile Path to the message file
 * @param bool $useTor Whether to force Tor usage
 * @return array Array containing success status, error message, and output
 */
function sendYamnEmail($chain, $copies, $messageFile, $useTor = false) {
    logDebug("=== Starting sendYamnEmail (Static Config Mode) ===");
    logDebug("Chain: $chain");
    logDebug("Copies: $copies");
    logDebug("Message file: $messageFile");
    logDebug("Use Tor: " . ($useTor ? "YES" : "NO"));

    // Configure environment for YAMN to use Tor if needed
    configureTorForYamn($useTor);

    // Check if message file exists
    if (!file_exists($messageFile)) {
        $error = "Message file does not exist: $messageFile";
        logDebug("ERROR: $error");
        return [
            'success' => false,
            'error' => $error,
            'relay_used' => null,
            'output' => []
        ];
    }

    // Verifica che il config file esista
    if (!file_exists(YAMN_CONFIG)) {
        $error = "Config file does not exist: " . YAMN_CONFIG;
        logDebug("ERROR: $error");
        return [
            'success' => false,
            'error' => $error,
            'relay_used' => null,
            'output' => []
        ];
    }

    // Build YAMN command to add message to pool
    $command_add_to_pool = YAMN_PATH . " " .
                          "--config=" . YAMN_CONFIG . " " .
                          "--mail " .
                          "--chain=\"$chain\" " .
                          "--copies=$copies < " . escapeshellarg($messageFile) . " 2>&1";

    // Command to send emails in pool
    $command_send = YAMN_PATH . " " .
                   "--config=" . YAMN_CONFIG . " -S 2>&1";

    // Log the commands
    logDebug("Add to pool command: $command_add_to_pool");

    // Execute add to pool command
    logDebug("Executing add to pool command...");
    exec($command_add_to_pool, $output_add_to_pool, $return_var_add_to_pool);

    // Log the output and return code
    logDebug("Add to pool output: " . implode("\n", $output_add_to_pool));
    logDebug("Add to pool return code: $return_var_add_to_pool");

    // Initialize send variables
    $output_send = [];
    $return_var_send = -1;

    // Only execute send command if add to pool was successful
    if ($return_var_add_to_pool == 0) {
        logDebug("Send command: $command_send");
        logDebug("Executing send command...");
        exec($command_send, $output_send, $return_var_send);
        logDebug("Send output: " . implode("\n", $output_send));
        logDebug("Send return code: $return_var_send");
    } else {
        logDebug("Skipping send command due to add to pool failure");
        $output_send = ["Skipped - add to pool command failed"];
        $return_var_send = -1;
    }

    // Check if succeeded
    $success = ($return_var_send == 0 && $return_var_add_to_pool == 0);

    if ($success) {
        // SUCCESS! Log and return
        $log_entry = date('Y-m-d H:i:s') . " | SUCCESS | Chain: $chain | Copies: $copies | Tor: " .
                     ($useTor ? "Yes" : "No") . "\n";
        file_put_contents('/var/www/yamnweb/yamn_send.log', $log_entry, FILE_APPEND);

        logDebug("✓ SUCCESS");
        logDebug("=== End sendYamnEmail ===");

        return [
            'success' => true,
            'error' => '',
            'relay_used' => 'Static Config',
            'tor_used' => $useTor,
            'outputs' => [
                'add_to_pool' => $output_add_to_pool,
                'send' => $output_send
            ]
        ];
    } else {
        // Failed
        $lastError = "Failed to send message";
        if ($return_var_add_to_pool != 0) {
            $lastError = "Failed to add message to pool: " . implode(" ", $output_add_to_pool);
        } elseif ($return_var_send != 0) {
            $lastError = "Failed to send from pool: " . implode(" ", $output_send);
        }

        $log_entry = date('Y-m-d H:i:s') . " | FAILED | Chain: $chain | Copies: $copies | Tor: " .
                     ($useTor ? "Yes" : "No") . " | Error: $lastError\n";
        file_put_contents('/var/www/yamnweb/yamn_send.log', $log_entry, FILE_APPEND);

        logDebug("✗ FAILED: $lastError");
        logDebug("=== End sendYamnEmail ===");

        return [
            'success' => false,
            'error' => $lastError,
            'relay_used' => null,
            'tor_used' => $useTor,
            'outputs' => [
                'add_to_pool' => $output_add_to_pool,
                'send' => $output_send
            ]
        ];
    }
}