upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tor.cpp142
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)
115static bool WriteTextFile(const std::string& path, const std::string& data, 118static 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
338static 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
383static 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
397static 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
404static 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
316static void ThreadManagedTorHostname(void*) 432static 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
361bool BtfStartManagedTor(const std::string& torPathOpt, std::string& errOut) 474bool 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}