Skip to content

Commit

Permalink
Merge pull request #108 from Psiphon-Inc/next-release
Browse files Browse the repository at this point in the history
Next release
  • Loading branch information
adamkruger authored Apr 26, 2022
2 parents 44016ae + 1f3c720 commit 96b3910
Show file tree
Hide file tree
Showing 22 changed files with 497 additions and 359 deletions.
Binary file modified src/3rdParty/psicash/Debug2015/psicash.lib
Binary file not shown.
Binary file modified src/3rdParty/psicash/Debug2015/psicash.pdb
Binary file not shown.
Binary file modified src/3rdParty/psicash/Release2015/psicash.lib
Binary file not shown.
2 changes: 1 addition & 1 deletion src/3rdParty/psicash/git.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.3.0-0-gdd95614
v2.3.1-0-ge96df62
Binary file modified src/3rdParty/psiphon-tunnel-core.exe
Binary file not shown.
123 changes: 83 additions & 40 deletions src/coretransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ using namespace std::experimental;


#define AUTOMATICALLY_ASSIGNED_PORT_NUMBER 0
#define EXE_NAME _T("psiphon-tunnel-core.exe")
#define URL_PROXY_EXE_NAME _T("psiphon-url-proxy.exe")
#define MAX_LEGACY_SERVER_ENTRIES 30
#define LEGACY_SERVER_ENTRY_LIST_NAME (string(LOCAL_SETTINGS_REGISTRY_VALUE_SERVERS) + "OSSH").c_str()

Expand Down Expand Up @@ -328,58 +326,103 @@ void CoreTransport::TransportConnectHelper()

bool CoreTransport::SpawnCoreProcess(const tstring& configFilename, const tstring& serverListFilename)
{
filesystem::path tempPath;
if (!GetSysTempPath(tempPath)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetSysTempPath failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
return false;
}
// When Settings::ExposeLocalProxiesToLAN is true, we are exposing the local proxy
// to the LAN (i.e., listen on all IP addresses; allow connections from external
// clients) there is a Windows Firewall prompt to allow the subprocess -- by path
// and name -- to accept external connections. In that case there are two things
// we don't want to do:
// 1. Show a new prompt every time there's a connection attempt and a new
// subprocess is spawned. This means that we can't use a random name every time.
// 2. Show a prompt with an filename that is unintelligible to the user. This means
// that we don't want to use a random name at all.
bool useFixedSubprocessName = Settings::ExposeLocalProxiesToLAN();

bool startSuccess = false;
for (int i = 0; i < 5; i++) {
if (i > 0 && useFixedSubprocessName) {
// We've already had our one attempt
break;
}

filesystem::path exePath;
if (RequestingUrlProxyWithoutTunnel())
{
exePath = tempPath / URL_PROXY_EXE_NAME;
tstring exePath;
if (useFixedSubprocessName) {
filesystem::path tempPath;
if (!GetSysTempPath(tempPath)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetSysTempPath failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
return false;
}

// In RequestingUrlProxyWithoutTunnel mode, we allow for multiple instances
// so we don't fail extract if the file already exists -- and don't try to
// kill any associated process holding a lock on it.
if (!ExtractExecutable(IDR_PSIPHON_TUNNEL_CORE_EXE, exePath, true))
exePath = tempPath / "psiphon-tunnel-core.exe";
}
else {
// We will be using a random file name for the executable. This will help
// prevent blocking of "psiphon-tunnel-core.exe". See:
// https://github.com/Psiphon-Inc/psiphon-issues/issues/828
// The goal is to make the running of this file as unblockable as possible,
// for example by a Windows Group Policy. Originally we always used the the
// same filename and it was trivially blocked from running. We are now using a
// filename with random length and random characters, under a random depth of
// subdirectories, which should be extremely difficult to create a glob-based
// matching rule for.
// The extension is also only included half the time. We will make multiple
// attempts to ensure that various filename configurations are tried.
if (!GetUniqueTempFilename(_T(".exe"), exePath, i)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetUniqueTempFilename failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
// This is unlikely to be recoverable with more attempts
return false;
}
}

if (RequestingUrlProxyWithoutTunnel())
{
my_print(NOT_SENSITIVE, true, _T("%s:%d - ExtractExecutable failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
// In RequestingUrlProxyWithoutTunnel mode, we allow for multiple instances
// so we don't fail extract if the file already exists -- and don't try to
// kill any associated process holding a lock on it.
if (!ExtractExecutable(IDR_PSIPHON_TUNNEL_CORE_EXE, exePath, true))
{
my_print(NOT_SENSITIVE, true, _T("%s:%d - ExtractExecutable failed: %d"), __TFUNCTION__, __LINE__, GetLastError());

// This string contains PII (the username in the temp path) but won't be logged
auto errorDetail = WStringToUTF8(exePath.tstring() + L"\n\n" + SystemErrorMessage(GetLastError()));
UI_Notice("PsiphonUI::FileError", errorDetail);
// This string contains PII (the username in the temp path) but won't be logged
auto errorDetail = WStringToUTF8(exePath + L"\n\n" + SystemErrorMessage(GetLastError()));
UI_Notice("PsiphonUI::FileError", errorDetail);

return false;
continue;
}
}
}
else
{
exePath = tempPath / EXE_NAME;

if (!ExtractExecutable(IDR_PSIPHON_TUNNEL_CORE_EXE, exePath))
else
{
my_print(NOT_SENSITIVE, true, _T("%s:%d - ExtractExecutable failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
if (!ExtractExecutable(IDR_PSIPHON_TUNNEL_CORE_EXE, exePath))
{
my_print(NOT_SENSITIVE, true, _T("%s:%d - ExtractExecutable failed: %d"), __TFUNCTION__, __LINE__, GetLastError());

// This string contains PII (the username in the temp path) but won't be logged
auto errorDetail = WStringToUTF8(exePath.tstring() + L"\n\n" + SystemErrorMessage(GetLastError()));
UI_Notice("PsiphonUI::FileError", errorDetail);
// This string contains PII (the username in the temp path) but won't be logged
auto errorDetail = WStringToUTF8(exePath + L"\n\n" + SystemErrorMessage(GetLastError()));
UI_Notice("PsiphonUI::FileError", errorDetail);

return false;
continue;
}
}
}

tstringstream commandLineFlags;
commandLineFlags << _T(" --config \"") << configFilename << _T("\"");
tstringstream commandLineFlags;
commandLineFlags << _T(" --config \"") << configFilename << _T("\"");

if (!RequestingUrlProxyWithoutTunnel())
{
commandLineFlags << _T(" --serverList \"") << serverListFilename << _T("\"");
if (!RequestingUrlProxyWithoutTunnel())
{
commandLineFlags << _T(" --serverList \"") << serverListFilename << _T("\"");
}

m_psiphonTunnelCore = make_unique<PsiphonTunnelCore>(this, exePath);
if (!m_psiphonTunnelCore->SpawnSubprocess(commandLineFlags.str())) {
my_print(NOT_SENSITIVE, false, _T("%s:%d - SpawnSubprocess failed"), __TFUNCTION__, __LINE__);
continue;
}

startSuccess = true;
break;
}

m_psiphonTunnelCore = make_unique<PsiphonTunnelCore>(this, exePath);
if (!m_psiphonTunnelCore->SpawnSubprocess(commandLineFlags.str())) {
my_print(NOT_SENSITIVE, false, _T("%s:%d - SpawnSubprocess failed"), __TFUNCTION__, __LINE__);
if (!startSuccess) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - process spawning failed utterly: %d"), __TFUNCTION__, __LINE__, GetLastError());
return false;
}

Expand Down
51 changes: 30 additions & 21 deletions src/feedback_upload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@

using namespace std::experimental;

#define EXE_NAME _T("feedback-upload.exe")

// IWorkerThread boilerplate

void FeedbackUpload::StartSendFeedback()
Expand Down Expand Up @@ -168,31 +166,42 @@ void FeedbackUpload::SendFeedbackHelper()

bool FeedbackUpload::SpawnFeedbackUploadProcess(const tstring& configFilename, const string& diagnosticData)
{
filesystem::path tempPath;
if (!GetSysTempPath(tempPath)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetSysTempPath failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
return false;
}
bool startSuccess = false;
for (int i = 0; i < 5; i++) {
tstring exePath;
if (!GetUniqueTempFilename(_T(".exe"), exePath, i)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetUniqueTempFilename failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
// This is unlikely to be recoverable with more attempts
return false;
}

auto exePath = tempPath / EXE_NAME;
if (!ExtractExecutable(IDR_PSIPHON_TUNNEL_CORE_EXE, exePath))
{
my_print(NOT_SENSITIVE, true, _T("%s:%d - ExtractExecutable failed: %d"), __TFUNCTION__, __LINE__, GetLastError());

if (!ExtractExecutable(IDR_PSIPHON_TUNNEL_CORE_EXE, exePath))
{
my_print(NOT_SENSITIVE, true, _T("%s:%d - ExtractExecutable failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
// This string contains PII (the username in the temp path) but won't be logged
auto errorDetail = WStringToUTF8(exePath + L"\n\n" + SystemErrorMessage(GetLastError()));
UI_Notice("PsiphonUI::FileError", errorDetail);

// This string contains PII (the username in the temp path) but won't be logged
auto errorDetail = WStringToUTF8(exePath.tstring() + L"\n\n" + SystemErrorMessage(GetLastError()));
UI_Notice("PsiphonUI::FileError", errorDetail);
continue;
}

return false;
}
tstringstream commandLineFlags;
commandLineFlags << _T(" --config \"") << configFilename << _T("\" --feedbackUpload");

tstringstream commandLineFlags;
commandLineFlags << _T(" --config \"") << configFilename << _T("\" --feedbackUpload");
m_psiphonTunnelCore = make_unique<PsiphonTunnelCore>(this, exePath);
if (!m_psiphonTunnelCore->SpawnSubprocess(commandLineFlags.str())) {
my_print(NOT_SENSITIVE, false, _T("%s:%d - SpawnSubprocess failed"), __TFUNCTION__, __LINE__);
// The PsiphonTunnelCore (Subprocess) destructor will clean up the executable file
continue;
}

startSuccess = true;
break;
}

m_psiphonTunnelCore = make_unique<PsiphonTunnelCore>(this, exePath);
if (!m_psiphonTunnelCore->SpawnSubprocess(commandLineFlags.str())) {
my_print(NOT_SENSITIVE, false, _T("%s:%d - SpawnSubprocess failed"), __TFUNCTION__, __LINE__);
if (!startSuccess) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - process spawning failed utterly: %d"), __TFUNCTION__, __LINE__, GetLastError());
return false;
}

Expand Down
86 changes: 55 additions & 31 deletions src/local_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@


#define POLIPO_CONNECTION_TIMEOUT_SECONDS 20
#define POLIPO_EXE_NAME _T("psiphon3-polipo.exe")


LocalProxy::LocalProxy(
Expand Down Expand Up @@ -89,49 +88,59 @@ void LocalProxy::UpdateSessionInfo(const SessionInfo& sessionInfo)

bool LocalProxy::DoStart()
{
if (m_polipoPath.size() == 0)
{
filesystem::path tempPath;
if (!GetSysTempPath(tempPath)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetSysTempPath failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
// Ensure we start from a disconnected/clean state
Cleanup(false);

int localHttpProxyPort = Settings::LocalHttpProxyPort();

bool startSuccess = false;
for (int i = 0; i < 5; i++) {
if (!GetUniqueTempFilename(_T(".exe"), m_polipoPath, i)) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - GetUniqueTempFilename failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
// This is unlikely to be recoverable with more attempts
return false;
}

m_polipoPath = tempPath / POLIPO_EXE_NAME;

if (!ExtractExecutable(IDR_POLIPO_EXE, m_polipoPath))
{
return false;
continue;
}
}

// Ensure we start from a disconnected/clean state
Cleanup(false);

int localHttpProxyPort = Settings::LocalHttpProxyPort();
if (localHttpProxyPort == 0)
{
// Choose the port automatically
localHttpProxyPort = 1024;
if (!TestForOpenPort(localHttpProxyPort, 60000, m_stopInfo))
if (localHttpProxyPort == 0)
{
my_print(NOT_SENSITIVE, false, _T("HTTP proxy could not find an available port."));
return false;
// Choose the port automatically
localHttpProxyPort = 1024;
if (!TestForOpenPort(localHttpProxyPort, 60000, m_stopInfo))
{
my_print(NOT_SENSITIVE, false, _T("HTTP proxy could not find an available port."));
// This is unlikely to be recoverable with more attempts
return false;
}
}
}
else
{
// Require the specified port
if (!TestForOpenPort(localHttpProxyPort, 0, m_stopInfo))
else
{
my_print(NOT_SENSITIVE, false, _T("Port is not available for HTTP proxy to listen on: %d"), localHttpProxyPort);
return false;
// Require the specified port
if (!TestForOpenPort(localHttpProxyPort, 0, m_stopInfo))
{
my_print(NOT_SENSITIVE, false, _T("Port is not available for HTTP proxy to listen on: %d"), localHttpProxyPort);
// This is unlikely to be recoverable with more attempts
return false;
}
}

if (!StartPolipo(localHttpProxyPort))
{
// The executable file is deleted by Cleanup
Cleanup(false);
continue;
}

startSuccess = true;
break;
}

if (!StartPolipo(localHttpProxyPort))
{
Cleanup(false);
if (!startSuccess) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - startup failed utterly: %d"), __TFUNCTION__, __LINE__, GetLastError());
return false;
}

Expand Down Expand Up @@ -204,6 +213,21 @@ void LocalProxy::DoStop(bool cleanly)

void LocalProxy::Cleanup(bool doStats)
{
auto deleteExe = finally([=]() {
if (!m_polipoPath.empty() && !DeleteFile(m_polipoPath.c_str()))
{
// We sometimes see random DeleteFile failures with ERROR_ACCESS_DENIED.
// This may be due to ongoing virus scanning of a newly written executable.
// Sleeping seems effective in allowing a subsequent DeleteFile to succeed,
// although the exact time needed to sleep surely varies by system.
Sleep(1000);
if (!DeleteFile(m_polipoPath.c_str())) {
my_print(NOT_SENSITIVE, true, _T("%s:%d - DeleteFile failed: %d"), __TFUNCTION__, __LINE__, GetLastError());
}
}
m_polipoPath.clear();
});

// Give the process an opportunity for graceful shutdown, then terminate
if (m_polipoProcessInfo.hProcess != 0
&& m_polipoProcessInfo.hProcess != INVALID_HANDLE_VALUE)
Expand Down
2 changes: 1 addition & 1 deletion src/psiphon_tunnel_core_utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ bool WriteParameterFiles(const WriteParameterFilesIn& in, WriteParameterFilesOut
// as each other. So we'll give each one a unique, temporary directory.

tstring tempDir;
if (!GetUniqueTempDir(tempDir, true))
if (!GetUniqueTempDir(tempDir))
{
my_print(NOT_SENSITIVE, false, _T("%s - GetUniqueTempDir failed (%d)"), __TFUNCTION__, GetLastError());
return false;
Expand Down
Loading

0 comments on commit 96b3910

Please sign in to comment.