diff --git a/src/ssh_session_backend.cpp b/src/ssh_session_backend.cpp index 0795663..8aa93bf 100644 --- a/src/ssh_session_backend.cpp +++ b/src/ssh_session_backend.cpp @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include namespace { QString escapeForShellSingleQuotes(const QString& value) @@ -33,8 +33,7 @@ SshSessionBackend::SshSessionBackend(const Profile& profile, QObject* parent) m_connectedProbeTimer(new QTimer(this)), m_state(SessionState::Disconnected), m_userInitiatedDisconnect(false), - m_reconnectPending(false), - m_askPassScript(nullptr) + m_reconnectPending(false) { m_connectedProbeTimer->setSingleShot(true); @@ -325,21 +324,26 @@ bool SshSessionBackend::configureAskPass(const SessionConnectOptions& options, QProcessEnvironment& environment, QString& error) { + cleanupAskPassScript(); + #ifdef Q_OS_WIN - m_askPassScript = new QTemporaryFile(QDir::tempPath() + QStringLiteral("/orbithub_askpass_XXXXXX.cmd"), - this); + m_askPassScriptPath = QDir::temp().filePath( + QStringLiteral("orbithub_askpass_%1.cmd") + .arg(QUuid::createUuid().toString(QUuid::WithoutBraces))); #else - m_askPassScript = new QTemporaryFile(QDir::tempPath() + QStringLiteral("/orbithub_askpass_XXXXXX.sh"), - this); + m_askPassScriptPath = QDir::temp().filePath( + QStringLiteral("orbithub_askpass_%1.sh") + .arg(QUuid::createUuid().toString(QUuid::WithoutBraces))); #endif - if (!m_askPassScript->open()) { + QFile script(m_askPassScriptPath); + if (!script.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { error = QStringLiteral("Failed to create temporary askpass helper script."); cleanupAskPassScript(); return false; } - QTextStream out(m_askPassScript); + QTextStream out(&script); #ifdef Q_OS_WIN out << "@echo off\r\n"; out << "echo " << escapedForWindowsEcho(options.password) << "\r\n"; @@ -348,15 +352,18 @@ bool SshSessionBackend::configureAskPass(const SessionConnectOptions& options, out << "printf '%s\\n' '" << escapeForShellSingleQuotes(options.password) << "'\n"; #endif out.flush(); - m_askPassScript->flush(); - m_askPassScript->close(); + script.close(); #ifndef Q_OS_WIN - QFile::setPermissions(m_askPassScript->fileName(), - QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner); + if (!QFile::setPermissions(m_askPassScriptPath, + QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner)) { + error = QStringLiteral("Failed to set permissions on askpass helper script."); + cleanupAskPassScript(); + return false; + } #endif - environment.insert(QStringLiteral("SSH_ASKPASS"), m_askPassScript->fileName()); + environment.insert(QStringLiteral("SSH_ASKPASS"), m_askPassScriptPath); environment.insert(QStringLiteral("SSH_ASKPASS_REQUIRE"), QStringLiteral("force")); if (!environment.contains(QStringLiteral("DISPLAY"))) { environment.insert(QStringLiteral("DISPLAY"), QStringLiteral(":0")); @@ -367,9 +374,9 @@ bool SshSessionBackend::configureAskPass(const SessionConnectOptions& options, void SshSessionBackend::cleanupAskPassScript() { - if (m_askPassScript != nullptr) { - delete m_askPassScript; - m_askPassScript = nullptr; + if (!m_askPassScriptPath.isEmpty()) { + QFile::remove(m_askPassScriptPath); + m_askPassScriptPath.clear(); } } @@ -402,6 +409,9 @@ QString SshSessionBackend::mapSshError(const QString& rawError) const if (raw.contains(QStringLiteral("No such file or directory"), Qt::CaseInsensitive)) { return QStringLiteral("Required file was not found."); } + if (raw.contains(QStringLiteral("Text file busy"), Qt::CaseInsensitive)) { + return QStringLiteral("Credential helper could not start (text file busy). Retry the connection."); + } if (raw.isEmpty()) { return QStringLiteral("SSH connection failed for an unknown reason."); } diff --git a/src/ssh_session_backend.h b/src/ssh_session_backend.h index 60fd312..9c92576 100644 --- a/src/ssh_session_backend.h +++ b/src/ssh_session_backend.h @@ -7,8 +7,6 @@ #include #include -class QTemporaryFile; - class SshSessionBackend : public SessionBackend { Q_OBJECT @@ -37,7 +35,7 @@ private: bool m_reconnectPending; SessionConnectOptions m_reconnectOptions; QString m_lastRawError; - QTemporaryFile* m_askPassScript; + QString m_askPassScriptPath; void setState(SessionState state, const QString& message); bool startSshProcess(const SessionConnectOptions& options);