diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/tor.cpp | 142 |
1 files changed, 134 insertions, 8 deletions
diff --git a/src/tor.cpp b/src/tor.cpp index 30a6f0b..0a1f48e 100644 --- a/src/tor.cpp +++ b/src/tor.cpp | |||
| @@ -101,7 +101,10 @@ static bool EnsureDir(const std::string& path, std::string& errOut) | |||
| 101 | if (stat(path.c_str(), &st) == 0) | 101 | if (stat(path.c_str(), &st) == 0) |
| 102 | { | 102 | { |
| 103 | if (S_ISDIR(st.st_mode)) | 103 | if (S_ISDIR(st.st_mode)) |
| 104 | { | ||
| 105 | chmod(path.c_str(), 0700); | ||
| 104 | return true; | 106 | return true; |
| 107 | } | ||
| 105 | errOut = strprintf("%s exists and is not a directory", path.c_str()); | 108 | errOut = strprintf("%s exists and is not a directory", path.c_str()); |
| 106 | return false; | 109 | return false; |
| 107 | } | 110 | } |
| @@ -115,10 +118,11 @@ static bool EnsureDir(const std::string& path, std::string& errOut) | |||
| 115 | static bool WriteTextFile(const std::string& path, const std::string& data, | 118 | static bool WriteTextFile(const std::string& path, const std::string& data, |
| 116 | std::string& errOut) | 119 | std::string& errOut) |
| 117 | { | 120 | { |
| 118 | FILE* f = fopen(path.c_str(), "wb"); | 121 | std::string tmp = path + ".tmp"; |
| 122 | FILE* f = fopen(tmp.c_str(), "wb"); | ||
| 119 | if (!f) | 123 | if (!f) |
| 120 | { | 124 | { |
| 121 | errOut = strprintf("could not write %s", path.c_str()); | 125 | errOut = strprintf("could not write %s", tmp.c_str()); |
| 122 | return false; | 126 | return false; |
| 123 | } | 127 | } |
| 124 | bool ok = fwrite(data.data(), 1, data.size(), f) == data.size(); | 128 | bool ok = fwrite(data.data(), 1, data.size(), f) == data.size(); |
| @@ -126,9 +130,27 @@ static bool WriteTextFile(const std::string& path, const std::string& data, | |||
| 126 | ok = false; | 130 | ok = false; |
| 127 | if (!ok) | 131 | if (!ok) |
| 128 | { | 132 | { |
| 129 | errOut = strprintf("could not finish writing %s", path.c_str()); | 133 | remove(tmp.c_str()); |
| 134 | errOut = strprintf("could not finish writing %s", tmp.c_str()); | ||
| 130 | return false; | 135 | return false; |
| 131 | } | 136 | } |
| 137 | #ifdef _WIN32 | ||
| 138 | if (!MoveFileExA(tmp.c_str(), path.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) | ||
| 139 | { | ||
| 140 | remove(tmp.c_str()); | ||
| 141 | errOut = strprintf("could not install %s atomically (error %lu)", | ||
| 142 | path.c_str(), (unsigned long)GetLastError()); | ||
| 143 | return false; | ||
| 144 | } | ||
| 145 | #else | ||
| 146 | if (rename(tmp.c_str(), path.c_str()) != 0) | ||
| 147 | { | ||
| 148 | remove(tmp.c_str()); | ||
| 149 | errOut = strprintf("could not install %s atomically: %s", | ||
| 150 | path.c_str(), strerror(errno)); | ||
| 151 | return false; | ||
| 152 | } | ||
| 153 | #endif | ||
| 132 | return true; | 154 | return true; |
| 133 | } | 155 | } |
| 134 | 156 | ||
| @@ -313,6 +335,100 @@ static bool StartTorProcess(const std::string& torPath, const std::string& torrc | |||
| 313 | #endif | 335 | #endif |
| 314 | } | 336 | } |
| 315 | 337 | ||
| 338 | static bool ManagedTorProcessAlive(bool& fExited, int& nExitCode) | ||
| 339 | { | ||
| 340 | fExited = false; | ||
| 341 | nExitCode = 0; | ||
| 342 | #ifdef _WIN32 | ||
| 343 | HANDLE hProcess = NULL; | ||
| 344 | CRITICAL_BLOCK(cs_managedTor) | ||
| 345 | hProcess = g_managedTorProcess.hProcess; | ||
| 346 | if (!hProcess) | ||
| 347 | return false; | ||
| 348 | DWORD code = 0; | ||
| 349 | if (!GetExitCodeProcess(hProcess, &code)) | ||
| 350 | return false; | ||
| 351 | if (code != STILL_ACTIVE) | ||
| 352 | { | ||
| 353 | fExited = true; | ||
| 354 | nExitCode = (int)code; | ||
| 355 | return false; | ||
| 356 | } | ||
| 357 | return true; | ||
| 358 | #else | ||
| 359 | pid_t pid = -1; | ||
| 360 | CRITICAL_BLOCK(cs_managedTor) | ||
| 361 | pid = g_managedTorPid; | ||
| 362 | if (pid <= 0) | ||
| 363 | return false; | ||
| 364 | int status = 0; | ||
| 365 | pid_t r = waitpid(pid, &status, WNOHANG); | ||
| 366 | if (r == 0) | ||
| 367 | return true; | ||
| 368 | if (r == pid) | ||
| 369 | { | ||
| 370 | fExited = true; | ||
| 371 | if (WIFEXITED(status)) | ||
| 372 | nExitCode = WEXITSTATUS(status); | ||
| 373 | else if (WIFSIGNALED(status)) | ||
| 374 | nExitCode = 128 + WTERMSIG(status); | ||
| 375 | CRITICAL_BLOCK(cs_managedTor) | ||
| 376 | if (g_managedTorPid == pid) | ||
| 377 | g_managedTorPid = -1; | ||
| 378 | } | ||
| 379 | return false; | ||
| 380 | #endif | ||
| 381 | } | ||
| 382 | |||
| 383 | static bool ValidateManagedTorStartup(std::string& errOut) | ||
| 384 | { | ||
| 385 | Sleep(500); | ||
| 386 | bool fExited = false; | ||
| 387 | int nExitCode = 0; | ||
| 388 | if (ManagedTorProcessAlive(fExited, nExitCode)) | ||
| 389 | return true; | ||
| 390 | if (fExited) | ||
| 391 | errOut = strprintf("Tor exited during startup with code %d", nExitCode); | ||
| 392 | else | ||
| 393 | errOut = "Tor process is not running after startup"; | ||
| 394 | return false; | ||
| 395 | } | ||
| 396 | |||
| 397 | static void MarkManagedTorDead(int nExitCode) | ||
| 398 | { | ||
| 399 | BtfStopManagedTor(); | ||
| 400 | CRITICAL_BLOCK(cs_managedTor) | ||
| 401 | g_managedTorStatus = strprintf("stopped unexpectedly, Tor exit code %d", nExitCode); | ||
| 402 | } | ||
| 403 | |||
| 404 | static void ThreadManagedTorWatchdog(void*) | ||
| 405 | { | ||
| 406 | for (;;) | ||
| 407 | { | ||
| 408 | Sleep(5000); | ||
| 409 | CRITICAL_BLOCK(cs_managedTor) | ||
| 410 | { | ||
| 411 | if (!g_fManagedTor || g_fManagedTorStopping || fShutdown) | ||
| 412 | return; | ||
| 413 | } | ||
| 414 | |||
| 415 | bool fExited = false; | ||
| 416 | int nExitCode = 0; | ||
| 417 | if (!ManagedTorProcessAlive(fExited, nExitCode)) | ||
| 418 | { | ||
| 419 | if (fExited) | ||
| 420 | MarkManagedTorDead(nExitCode); | ||
| 421 | else | ||
| 422 | { | ||
| 423 | BtfStopManagedTor(); | ||
| 424 | CRITICAL_BLOCK(cs_managedTor) | ||
| 425 | g_managedTorStatus = "stopped unexpectedly, Tor process handle is gone"; | ||
| 426 | } | ||
| 427 | return; | ||
| 428 | } | ||
| 429 | } | ||
| 430 | } | ||
| 431 | |||
| 316 | static void ThreadManagedTorHostname(void*) | 432 | static void ThreadManagedTorHostname(void*) |
| 317 | { | 433 | { |
| 318 | std::string hostnamePath; | 434 | std::string hostnamePath; |
| @@ -350,12 +466,9 @@ static void ThreadManagedTorHostname(void*) | |||
| 350 | Sleep(1000); | 466 | Sleep(1000); |
| 351 | } | 467 | } |
| 352 | 468 | ||
| 469 | BtfStopManagedTor(); | ||
| 353 | CRITICAL_BLOCK(cs_managedTor) | 470 | CRITICAL_BLOCK(cs_managedTor) |
| 354 | { | 471 | g_managedTorStatus = "failed: Tor did not create a hidden service hostname within 90s"; |
| 355 | if (!g_fManagedTorStopping) | ||
| 356 | g_managedTorStatus = strprintf("running, SOCKS5 127.0.0.1:%u, waiting for hidden service hostname", | ||
| 357 | (unsigned)g_managedTorSocksPort); | ||
| 358 | } | ||
| 359 | } | 472 | } |
| 360 | 473 | ||
| 361 | bool BtfStartManagedTor(const std::string& torPathOpt, std::string& errOut) | 474 | bool BtfStartManagedTor(const std::string& torPathOpt, std::string& errOut) |
| @@ -411,6 +524,13 @@ bool BtfStartManagedTor(const std::string& torPathOpt, std::string& errOut) | |||
| 411 | } | 524 | } |
| 412 | return false; | 525 | return false; |
| 413 | } | 526 | } |
| 527 | if (!ValidateManagedTorStartup(errOut)) | ||
| 528 | { | ||
| 529 | BtfStopManagedTor(); | ||
| 530 | CRITICAL_BLOCK(cs_managedTor) | ||
| 531 | g_managedTorStatus = strprintf("failed: %s", errOut.c_str()); | ||
| 532 | return false; | ||
| 533 | } | ||
| 414 | 534 | ||
| 415 | std::string proxyErr; | 535 | std::string proxyErr; |
| 416 | if (!BtfEnableTorProxy(strprintf("127.0.0.1:%u", (unsigned)socksPort), proxyErr)) | 536 | if (!BtfEnableTorProxy(strprintf("127.0.0.1:%u", (unsigned)socksPort), proxyErr)) |
| @@ -426,6 +546,12 @@ bool BtfStartManagedTor(const std::string& torPathOpt, std::string& errOut) | |||
| 426 | errOut = "could not start managed Tor hostname watcher"; | 546 | errOut = "could not start managed Tor hostname watcher"; |
| 427 | return false; | 547 | return false; |
| 428 | } | 548 | } |
| 549 | if (_beginthread(ThreadManagedTorWatchdog, 0, NULL) == (uintptr_t)-1) | ||
| 550 | { | ||
| 551 | BtfStopManagedTor(); | ||
| 552 | errOut = "could not start managed Tor watchdog"; | ||
| 553 | return false; | ||
| 554 | } | ||
| 429 | 555 | ||
| 430 | return true; | 556 | return true; |
| 431 | } | 557 | } |