From 393ac100c883fda7eee79316e7624e00d8f67363 Mon Sep 17 00:00:00 2001 From: legonigel Date: Sun, 8 Mar 2015 23:21:15 -0400 Subject: [PATCH 01/49] Changed shortcut on main window gui for server The shortcut for the server checkbox on the main gui is now Alt-V. This deconflicts the start/stop button. Fixes #4367 --- src/gui/res/MainWindowBase.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/res/MainWindowBase.ui b/src/gui/res/MainWindowBase.ui index 88f07b27..73917975 100644 --- a/src/gui/res/MainWindowBase.ui +++ b/src/gui/res/MainWindowBase.ui @@ -87,7 +87,7 @@ - &Server (share this computer's mouse and keyboard): + Ser&ver (share this computer's mouse and keyboard): true From 07b1ea203f4c2355026a00294dd32f6af676e455 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 14 Apr 2015 17:29:08 +0100 Subject: [PATCH 02/49] Message box asking user to verify fingerprint #4522 --- src/gui/src/MainWindow.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index bd7caa28..234370ed 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -395,6 +395,34 @@ void MainWindow::updateStateFromLogLine(const QString &line) { setSynergyState(synergyConnected); } + + QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)"); + if (fingerprintRegex.exactMatch(line)) { + + QString fingerprint = fingerprintRegex.cap(1); + QMessageBox::StandardButton fingerprintReply = + QMessageBox::information( + this, tr("Security question"), + tr("Do you trust this fingerprint?\n\n" + "%1\n\n" + "This is a server fingerprint. You should compare this " + "fingerprint to the one on your server's screen. If the " + "two don't match exactly, then it's probably not the server " + "you're expecting (it could be a malicious user).\n\n" + "To automatically trust this fingerprint for future " + "connections, click Yes. To reject this fingerprint and " + "disconnect from the server, click No.") + .arg(fingerprint), + QMessageBox::Yes | QMessageBox::No); + + if (fingerprintReply == QMessageBox::Yes) { + // TODO: save to file + qDebug() << "fingerprint: " << fingerprint; + } + else { + stopSynergy(); + } + } } void MainWindow::clearLog() From 5dfe4aa0b515ab453e430442ac8e7c88586c83d9 Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Wed, 1 Apr 2015 16:04:10 +0100 Subject: [PATCH 03/49] Added verification of server certificate fingerprint #4522 Conflicts: src/lib/mt/Thread.cpp src/lib/plugin/ns/SecureSocket.cpp src/lib/synergy/ClientArgs.cpp --- src/lib/mt/Thread.cpp | 1 - src/lib/plugin/ns/SecureSocket.cpp | 79 +++++++++++++++++++++++++++--- src/lib/plugin/ns/SecureSocket.h | 10 ++++ src/lib/synergy/ArgParser.cpp | 4 ++ src/lib/synergy/ClientArgs.cpp | 5 +- src/lib/synergy/ClientArgs.h | 3 +- 6 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/lib/mt/Thread.cpp b/src/lib/mt/Thread.cpp index dd45d872..d77d0705 100644 --- a/src/lib/mt/Thread.cpp +++ b/src/lib/mt/Thread.cpp @@ -160,7 +160,6 @@ Thread::threadFunc(void* vjob) } catch (XSocket& e) { - // client called cancel() LOG((CLOG_DEBUG "%s", e.what())); } catch (XThreadCancel&) { diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index cb6db76f..facf8337 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -23,11 +23,13 @@ #include "arch/XArch.h" #include "base/Log.h" -#include #include #include #include #include +#include +#include +#include // // SecureSocket @@ -40,11 +42,14 @@ struct Ssl { SSL* m_ssl; }; -SecureSocket::SecureSocket( +bool CSecureSocket::s_verifyFingerprintFailed = false; + +CSecureSocket::CSecureSocket( IEventQueue* events, - SocketMultiplexer* socketMultiplexer) : - TCPSocket(events, socketMultiplexer), - m_secureReady(false) + CSocketMultiplexer* socketMultiplexer) : + CTCPSocket(events, socketMultiplexer), + m_secureReady(false), + m_certFingerprint() { } @@ -169,6 +174,8 @@ SecureSocket::loadCertificates(const char* filename) } } +const char test[] = "/Users/xinyu/serverCertificateFingerprint.txt"; + void SecureSocket::initContext(bool server) { @@ -197,6 +204,11 @@ SecureSocket::initContext(bool server) if (m_ssl->m_context == NULL) { showError(); } + + if (!server) { + //void* p = reinterpret_cast(const_cast(m_certFingerprint.c_str())); + SSL_CTX_set_cert_verify_callback(m_ssl->m_context, CSecureSocket::verifyCertFingerprint, (void*)test); + } } void @@ -261,6 +273,10 @@ SecureSocket::secureConnect(int socket) m_secureReady = !retry; + if (s_verifyFingerprintFailed) { + throwError("failed to verify server certificate fingerprint"); + } + if (m_secureReady) { LOG((CLOG_INFO "connected to secure socket")); showCertificate(); @@ -366,7 +382,7 @@ SecureSocket::throwError(const char* reason) String error = getError(); if (!error.empty()) { throw XSocket(synergy::string::sprintf( - "%s: %s", reason, error.c_str())); + "%s: %s", reason, error.c_str())); } else { throw XSocket(reason); @@ -419,3 +435,54 @@ SecureSocket::serviceAccept(ISocketMultiplexerJob* job, return retry ? job : newJob(); } + +int +CSecureSocket::verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg) +{ + X509 *cert = ctx->cert; + + EVP_MD* tempDigest; + unsigned char tempFingerprint[EVP_MAX_MD_SIZE]; + unsigned int tempFingerprintLen; + tempDigest = (EVP_MD*)EVP_sha1(); + if (X509_digest(cert, tempDigest, tempFingerprint, &tempFingerprintLen) <= 0) { + s_verifyFingerprintFailed = true; + return 0; + } + + std::stringstream ss; + ss << std::hex; + for (int i = 0; i < tempFingerprintLen; i++) { + ss << std::setw(2) << std::setfill('0') << (int)tempFingerprint[i]; + } + CString fingerprint = ss.str(); + std::transform(fingerprint.begin(), fingerprint.end(), fingerprint.begin(), ::toupper); + + CString fileLine; + CString certificateFingerprint; + char* certFingerprintFilename = reinterpret_cast(arg); + std::ifstream file; + file.open(certFingerprintFilename); + + while (!file.eof()) { + getline(file,fileLine); + size_t found = fileLine.find('='); + if (found != CString::npos) { + certificateFingerprint = fileLine.substr(found + 1); + + if (!certificateFingerprint.empty()) { + certificateFingerprint.erase(std::remove(certificateFingerprint.begin(), certificateFingerprint.end(), ':'), certificateFingerprint.end()); + + if(certificateFingerprint.compare(fingerprint) == 0) { + file.close(); + return 1; + } + } + } + } + + file.close(); + + s_verifyFingerprintFailed = true; + return 0; +} diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index d703d2ca..d184814c 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -20,6 +20,8 @@ #include "net/TCPSocket.h" #include "net/XSocket.h" +#include + class IEventQueue; class SocketMultiplexer; class ISocketMultiplexerJob; @@ -71,7 +73,15 @@ private: serviceAccept(ISocketMultiplexerJob*, bool, bool, bool); +private: +static int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg); + + private: Ssl* m_ssl; bool m_secureReady; + CString m_certFingerprint; + +private: + static bool s_verifyFingerprintFailed; }; diff --git a/src/lib/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index bec60632..7ba85752 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -89,6 +89,10 @@ ArgParser::parseClientArgs(ClientArgs& args, int argc, const char* const* argv) // define scroll args.m_yscroll = atoi(argv[++i]); } + else if (isArg(i, argc, argv, NULL, "--certificate-fingerprint", 1)) { + // define scroll + args.m_certFingerprint = argv[++i]; + } else { if (i + 1 == argc) { args.m_synergyAddress = argv[i]; diff --git a/src/lib/synergy/ClientArgs.cpp b/src/lib/synergy/ClientArgs.cpp index c997f3cc..efbbd90b 100644 --- a/src/lib/synergy/ClientArgs.cpp +++ b/src/lib/synergy/ClientArgs.cpp @@ -17,7 +17,8 @@ #include "synergy/ClientArgs.h" -ClientArgs::ClientArgs() : - m_yscroll(0) +CClientArgs::CClientArgs() : + m_yscroll(0), + m_certFingerprint() { } diff --git a/src/lib/synergy/ClientArgs.h b/src/lib/synergy/ClientArgs.h index db749b3e..f4024618 100644 --- a/src/lib/synergy/ClientArgs.h +++ b/src/lib/synergy/ClientArgs.h @@ -26,5 +26,6 @@ public: ClientArgs(); public: - int m_yscroll; + int m_yscroll; + CString m_certFingerprint; }; From b8ba37b4f4687a4bdd6160095ee10abecca7e841 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Wed, 1 Apr 2015 16:32:04 +0100 Subject: [PATCH 04/49] Made callback function global #4522 --- src/lib/plugin/ns/SecureSocket.cpp | 14 +++++++++----- src/lib/plugin/ns/SecureSocket.h | 8 +------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index facf8337..bf4d4c3b 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -23,6 +23,7 @@ #include "arch/XArch.h" #include "base/Log.h" +#include #include #include #include @@ -30,6 +31,9 @@ #include #include #include +#include + +int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg); // // SecureSocket @@ -207,7 +211,7 @@ SecureSocket::initContext(bool server) if (!server) { //void* p = reinterpret_cast(const_cast(m_certFingerprint.c_str())); - SSL_CTX_set_cert_verify_callback(m_ssl->m_context, CSecureSocket::verifyCertFingerprint, (void*)test); + SSL_CTX_set_cert_verify_callback(m_ssl->m_context, verifyCertFingerprint, (void*)test); } } @@ -437,7 +441,7 @@ SecureSocket::serviceAccept(ISocketMultiplexerJob* job, } int -CSecureSocket::verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg) +verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg) { X509 *cert = ctx->cert; @@ -446,13 +450,13 @@ CSecureSocket::verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg) unsigned int tempFingerprintLen; tempDigest = (EVP_MD*)EVP_sha1(); if (X509_digest(cert, tempDigest, tempFingerprint, &tempFingerprintLen) <= 0) { - s_verifyFingerprintFailed = true; + CSecureSocket::s_verifyFingerprintFailed = true; return 0; } std::stringstream ss; ss << std::hex; - for (int i = 0; i < tempFingerprintLen; i++) { + for (unsigned int i = 0; i < tempFingerprintLen; i++) { ss << std::setw(2) << std::setfill('0') << (int)tempFingerprint[i]; } CString fingerprint = ss.str(); @@ -483,6 +487,6 @@ CSecureSocket::verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg) file.close(); - s_verifyFingerprintFailed = true; + CSecureSocket::s_verifyFingerprintFailed = true; return 0; } diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index d184814c..507566e8 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -20,8 +20,6 @@ #include "net/TCPSocket.h" #include "net/XSocket.h" -#include - class IEventQueue; class SocketMultiplexer; class ISocketMultiplexerJob; @@ -73,15 +71,11 @@ private: serviceAccept(ISocketMultiplexerJob*, bool, bool, bool); -private: -static int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg); - - private: Ssl* m_ssl; bool m_secureReady; CString m_certFingerprint; -private: +public: static bool s_verifyFingerprintFailed; }; From 71dc472a64a81390294b53a4c803eac50adb18d3 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Wed, 1 Apr 2015 16:35:03 +0100 Subject: [PATCH 05/49] Fixed code style --- src/lib/plugin/ns/SecureSocket.cpp | 4 ++-- src/lib/synergy/ClientArgs.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index bf4d4c3b..6b38ec3c 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -33,8 +33,6 @@ #include #include -int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg); - // // SecureSocket // @@ -46,6 +44,8 @@ struct Ssl { SSL* m_ssl; }; +int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg); + bool CSecureSocket::s_verifyFingerprintFailed = false; CSecureSocket::CSecureSocket( diff --git a/src/lib/synergy/ClientArgs.h b/src/lib/synergy/ClientArgs.h index f4024618..c9ddb9e9 100644 --- a/src/lib/synergy/ClientArgs.h +++ b/src/lib/synergy/ClientArgs.h @@ -26,6 +26,6 @@ public: ClientArgs(); public: - int m_yscroll; - CString m_certFingerprint; + int m_yscroll; + CString m_certFingerprint; }; From b24eb2b724fde5f406a3d4ec5ab7aa235ea31518 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Wed, 1 Apr 2015 16:39:40 +0100 Subject: [PATCH 06/49] Removed test string #4522 --- src/lib/plugin/ns/SecureSocket.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 6b38ec3c..ecda101d 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -178,8 +178,6 @@ SecureSocket::loadCertificates(const char* filename) } } -const char test[] = "/Users/xinyu/serverCertificateFingerprint.txt"; - void SecureSocket::initContext(bool server) { @@ -210,8 +208,11 @@ SecureSocket::initContext(bool server) } if (!server) { - //void* p = reinterpret_cast(const_cast(m_certFingerprint.c_str())); - SSL_CTX_set_cert_verify_callback(m_ssl->m_context, verifyCertFingerprint, (void*)test); + void* p = reinterpret_cast(const_cast(m_certFingerprint.c_str())); + SSL_CTX_set_cert_verify_callback( + m_ssl->m_context, + verifyCertFingerprint, + p); } } From cb0f0dd06dba84617585fe18e01bcdaffedce4f5 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Thu, 2 Apr 2015 11:56:51 +0100 Subject: [PATCH 07/49] Improved fingerprint verification #4522 Conflicts: src/lib/plugin/ns/SecureSocket.cpp src/lib/plugin/ns/SecureSocket.h src/lib/synergy/ClientApp.cpp --- src/lib/plugin/ns/SecureSocket.cpp | 150 ++++++++++++++--------------- src/lib/plugin/ns/SecureSocket.h | 7 +- 2 files changed, 78 insertions(+), 79 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index ecda101d..56900461 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -44,10 +44,6 @@ struct Ssl { SSL* m_ssl; }; -int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg); - -bool CSecureSocket::s_verifyFingerprintFailed = false; - CSecureSocket::CSecureSocket( IEventQueue* events, CSocketMultiplexer* socketMultiplexer) : @@ -206,14 +202,6 @@ SecureSocket::initContext(bool server) if (m_ssl->m_context == NULL) { showError(); } - - if (!server) { - void* p = reinterpret_cast(const_cast(m_certFingerprint.c_str())); - SSL_CTX_set_cert_verify_callback( - m_ssl->m_context, - verifyCertFingerprint, - p); - } } void @@ -278,13 +266,15 @@ SecureSocket::secureConnect(int socket) m_secureReady = !retry; - if (s_verifyFingerprintFailed) { - throwError("failed to verify server certificate fingerprint"); - } - if (m_secureReady) { - LOG((CLOG_INFO "connected to secure socket")); - showCertificate(); + if (verifyCertFingerprint()) { + LOG((CLOG_INFO "connected to secure socket")); + showCertificate(); + } + else { + LOG((CLOG_ERR "failed to verity server certificate fingerprint")); + disconnect(); + } } return retry; @@ -367,8 +357,7 @@ SecureSocket::checkResult(int n, bool& fatal, bool& retry) if (fatal) { showError(); - sendEvent(getEvents()->forISocket().disconnected()); - sendEvent(getEvents()->forIStream().inputShutdown()); + disconnect(); } } @@ -409,11 +398,73 @@ SecureSocket::getError() } } +void +CSecureSocket::disconnect() +{ + sendEvent(getEvents()->forISocket().disconnected()); + sendEvent(getEvents()->forIStream().inputShutdown()); +} + +bool +CSecureSocket::verifyCertFingerprint() +{ + // calculate received certificate fingerprint + X509 *cert = cert = SSL_get_peer_certificate(m_ssl->m_ssl); + EVP_MD* tempDigest; + unsigned char tempFingerprint[EVP_MAX_MD_SIZE]; + unsigned int tempFingerprintLen; + tempDigest = (EVP_MD*)EVP_sha1(); + if (X509_digest(cert, tempDigest, tempFingerprint, &tempFingerprintLen) <= 0) { + return false; + } + + // convert fingerprint into hexdecimal format + std::stringstream ss; + ss << std::hex; + for (unsigned int i = 0; i < tempFingerprintLen; i++) { + ss << std::setw(2) << std::setfill('0') << (int)tempFingerprint[i]; + } + + // all uppercase + CString fingerprint = ss.str(); + std::transform(fingerprint.begin(), fingerprint.end(), fingerprint.begin(), ::toupper); + + // check if this fingerprint exist + CString fileLine; + CString certificateFingerprint; + std::ifstream file; + file.open(m_certFingerprint.c_str()); + + while (!file.eof()) { + getline(file,fileLine); + // example of a fingerprint: + // SHA1 Fingerprint=6E:41:1A:21:53:2E:A3:EF:4D:A6:F2:A6:BA:0E:27:09:8A:F3:A1:10 + size_t found = fileLine.find('='); + if (found != CString::npos) { + certificateFingerprint = fileLine.substr(found + 1); + + if (!certificateFingerprint.empty()) { + // remove colons + certificateFingerprint.erase(std::remove(certificateFingerprint.begin(), certificateFingerprint.end(), ':'), certificateFingerprint.end()); + + if(certificateFingerprint.compare(fingerprint) == 0) { + file.close(); + return true; + } + } + } + } + + file.close(); + + return false; +} + ISocketMultiplexerJob* -SecureSocket::serviceConnect(ISocketMultiplexerJob* job, +CSecureSocket::serviceConnect(ISocketMultiplexerJob* job, bool, bool write, bool error) { - Lock lock(&getMutex()); + CLock lock(&getMutex()); bool retry = true; #ifdef SYSAPI_WIN32 @@ -426,10 +477,10 @@ SecureSocket::serviceConnect(ISocketMultiplexerJob* job, } ISocketMultiplexerJob* -SecureSocket::serviceAccept(ISocketMultiplexerJob* job, +CSecureSocket::serviceAccept(ISocketMultiplexerJob* job, bool, bool write, bool error) { - Lock lock(&getMutex()); + CLock lock(&getMutex()); bool retry = true; #ifdef SYSAPI_WIN32 @@ -440,54 +491,3 @@ SecureSocket::serviceAccept(ISocketMultiplexerJob* job, return retry ? job : newJob(); } - -int -verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg) -{ - X509 *cert = ctx->cert; - - EVP_MD* tempDigest; - unsigned char tempFingerprint[EVP_MAX_MD_SIZE]; - unsigned int tempFingerprintLen; - tempDigest = (EVP_MD*)EVP_sha1(); - if (X509_digest(cert, tempDigest, tempFingerprint, &tempFingerprintLen) <= 0) { - CSecureSocket::s_verifyFingerprintFailed = true; - return 0; - } - - std::stringstream ss; - ss << std::hex; - for (unsigned int i = 0; i < tempFingerprintLen; i++) { - ss << std::setw(2) << std::setfill('0') << (int)tempFingerprint[i]; - } - CString fingerprint = ss.str(); - std::transform(fingerprint.begin(), fingerprint.end(), fingerprint.begin(), ::toupper); - - CString fileLine; - CString certificateFingerprint; - char* certFingerprintFilename = reinterpret_cast(arg); - std::ifstream file; - file.open(certFingerprintFilename); - - while (!file.eof()) { - getline(file,fileLine); - size_t found = fileLine.find('='); - if (found != CString::npos) { - certificateFingerprint = fileLine.substr(found + 1); - - if (!certificateFingerprint.empty()) { - certificateFingerprint.erase(std::remove(certificateFingerprint.begin(), certificateFingerprint.end(), ':'), certificateFingerprint.end()); - - if(certificateFingerprint.compare(fingerprint) == 0) { - file.close(); - return 1; - } - } - } - } - - file.close(); - - CSecureSocket::s_verifyFingerprintFailed = true; - return 0; -} diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 507566e8..725d5da9 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -61,7 +61,9 @@ private: void checkResult(int n, bool& fatal, bool& retry); void showError(); void throwError(const char* reason); - String getError(); + CString getError(); + void disconnect(); + bool verifyCertFingerprint(); ISocketMultiplexerJob* serviceConnect(ISocketMultiplexerJob*, @@ -75,7 +77,4 @@ private: Ssl* m_ssl; bool m_secureReady; CString m_certFingerprint; - -public: - static bool s_verifyFingerprintFailed; }; From 39e183da3efd87950a980f8770133d3b631298b4 Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Thu, 2 Apr 2015 14:01:50 +0100 Subject: [PATCH 08/49] Refactored string operations Conflicts: src/lib/base/String.cpp --- src/lib/base/String.cpp | 27 +++++++++++++++++++++++++++ src/lib/base/String.h | 19 +++++++++++++++++++ src/lib/plugin/ns/SecureSocket.cpp | 15 ++++----------- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/lib/base/String.cpp b/src/lib/base/String.cpp index 4ce38899..32531df8 100644 --- a/src/lib/base/String.cpp +++ b/src/lib/base/String.cpp @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include namespace synergy { namespace string { @@ -180,6 +183,30 @@ removeFileExt(String filename) return filename.substr(0, dot); } +void +toHex(CString& subject, int width, const char fill) +{ + std::stringstream ss; + ss << std::hex; + for (unsigned int i = 0; i < subject.length(); i++) { + ss << std::setw(width) << std::setfill(fill) << (int)(unsigned char)subject[i]; + } + + subject = ss.str(); +} + +void +uppercase(CString& subject) +{ + std::transform(subject.begin(), subject.end(), subject.begin(), ::toupper); +} + +void +removeChar(CString& subject, const char c) +{ + subject.erase(std::remove(subject.begin(), subject.end(), c), subject.end()); +} + // // CaselessCmp // diff --git a/src/lib/base/String.h b/src/lib/base/String.h index 9d137143..57f3c69c 100644 --- a/src/lib/base/String.h +++ b/src/lib/base/String.h @@ -70,6 +70,25 @@ Finds the last dot and remove all characters from the dot to the end */ String removeFileExt(String filename); +//! Convert into hexdecimal +/*! +Convert each character in \c subject into hexdecimal form with \c width +*/ +void toHex(CString& subject, int width, const char fill = '0'); + +//! Convert to all uppercase +/*! +Convert each character in \c subject to uppercase +*/ +void uppercase(CString& subject); + +//! Remove all specific char in suject +/*! +Remove all specific \c char in \c suject +*/ +void removeChar(CString& subject, const char c); + + //! Case-insensitive comparisons /*! This class provides case-insensitve comparison functions. diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 56900461..8821a3e6 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -28,10 +28,7 @@ #include #include #include -#include -#include #include -#include // // SecureSocket @@ -419,15 +416,11 @@ CSecureSocket::verifyCertFingerprint() } // convert fingerprint into hexdecimal format - std::stringstream ss; - ss << std::hex; - for (unsigned int i = 0; i < tempFingerprintLen; i++) { - ss << std::setw(2) << std::setfill('0') << (int)tempFingerprint[i]; - } + CString fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); + synergy::string::toHex(fingerprint, 2); // all uppercase - CString fingerprint = ss.str(); - std::transform(fingerprint.begin(), fingerprint.end(), fingerprint.begin(), ::toupper); + synergy::string::uppercase(fingerprint); // check if this fingerprint exist CString fileLine; @@ -445,7 +438,7 @@ CSecureSocket::verifyCertFingerprint() if (!certificateFingerprint.empty()) { // remove colons - certificateFingerprint.erase(std::remove(certificateFingerprint.begin(), certificateFingerprint.end(), ':'), certificateFingerprint.end()); + synergy::string::removeChar(certificateFingerprint, ':'); if(certificateFingerprint.compare(fingerprint) == 0) { file.close(); From b4665b9cd514a9c1ebbf78ac691fbeabefec3b23 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Thu, 2 Apr 2015 14:43:23 +0100 Subject: [PATCH 09/49] Passed args into client and socket Conflicts: src/lib/client/Client.cpp src/lib/client/Client.h src/lib/synergy/ClientApp.cpp src/test/integtests/net/NetworkTests.cpp --- src/lib/client/Client.cpp | 11 ++++++----- src/lib/client/Client.h | 5 +++-- src/lib/net/TCPSocket.h | 1 + src/lib/plugin/ns/SecureSocket.cpp | 8 ++++++-- src/lib/plugin/ns/SecureSocket.h | 3 ++- src/lib/synergy/ArgParser.cpp | 2 +- src/lib/synergy/ClientApp.cpp | 3 +-- src/lib/synergy/ClientArgs.cpp | 2 +- src/lib/synergy/ClientArgs.h | 2 +- src/test/integtests/net/NetworkTests.cpp | 24 +++++++++++++++++++----- 10 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 456260f0..43717134 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -60,8 +60,7 @@ Client::Client( const String& name, const NetworkAddress& address, ISocketFactory* socketFactory, synergy::Screen* screen, - bool enableDragDrop, - bool enableCrypto) : + ClientArgs args) : m_mock(false), m_name(name), m_serverAddress(address), @@ -77,9 +76,9 @@ Client::Client( m_events(events), m_sendFileThread(NULL), m_writeToDropDirThread(NULL), - m_enableDragDrop(enableDragDrop), m_socket(NULL), m_useSecureNetwork(false) + m_args(args) { assert(m_socketFactory != NULL); assert(m_screen != NULL); @@ -94,7 +93,7 @@ Client::Client( new TMethodEventJob(this, &Client::handleResume)); - if (m_enableDragDrop) { + if (m_args.m_enableDragDrop) { m_events->adoptHandler(m_events->forIScreen().fileChunkSending(), this, new TMethodEventJob(this, @@ -162,6 +161,7 @@ Client::connect() // create the socket IDataSocket* socket = m_socketFactory->create(m_useSecureNetwork); m_socket = dynamic_cast(socket); + m_socket->setFingerprintFilename(m_args.m_certFingerprintFilename); // filter socket messages, including a packetizing filter m_stream = socket; @@ -780,7 +780,8 @@ Client::fileChunkReceived(String data) void Client::dragInfoReceived(UInt32 fileNum, String data) { - if (!m_enableDragDrop) { + // TODO: fix duplicate function from CServer + if (!m_args.m_enableDragDrop) { LOG((CLOG_DEBUG "drag drop not enabled, ignoring drag info.")); return; } diff --git a/src/lib/client/Client.h b/src/lib/client/Client.h index f869ef64..12baadb4 100644 --- a/src/lib/client/Client.h +++ b/src/lib/client/Client.h @@ -23,6 +23,7 @@ #include "synergy/IClipboard.h" #include "synergy/DragInformation.h" #include "synergy/INode.h" +#include "synergy/ClientArgs.h" #include "net/NetworkAddress.h" #include "base/EventTypes.h" @@ -59,8 +60,7 @@ public: const String& name, const NetworkAddress& address, ISocketFactory* socketFactory, synergy::Screen* screen, - bool enableDragDrop, - bool enableCrypto); + ClientArgs args); ~Client(); #ifdef TEST_ENV @@ -227,4 +227,5 @@ private: bool m_enableDragDrop; TCPSocket* m_socket; bool m_useSecureNetwork; + ClientArgs m_args; }; diff --git a/src/lib/net/TCPSocket.h b/src/lib/net/TCPSocket.h index 832cd128..57bb0169 100644 --- a/src/lib/net/TCPSocket.h +++ b/src/lib/net/TCPSocket.h @@ -59,6 +59,7 @@ public: virtual void secureConnect() {} virtual void secureAccept() {} + virtual void setFingerprintFilename(CString& f) {} protected: ArchSocket getSocket() { return m_socket; } diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 8821a3e6..de63e333 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -46,7 +46,7 @@ CSecureSocket::CSecureSocket( CSocketMultiplexer* socketMultiplexer) : CTCPSocket(events, socketMultiplexer), m_secureReady(false), - m_certFingerprint() + m_certFingerprintFilename() { } @@ -405,6 +405,10 @@ CSecureSocket::disconnect() bool CSecureSocket::verifyCertFingerprint() { + if (m_certFingerprintFilename.empty()) { + return false; + } + // calculate received certificate fingerprint X509 *cert = cert = SSL_get_peer_certificate(m_ssl->m_ssl); EVP_MD* tempDigest; @@ -426,7 +430,7 @@ CSecureSocket::verifyCertFingerprint() CString fileLine; CString certificateFingerprint; std::ifstream file; - file.open(m_certFingerprint.c_str()); + file.open(m_certFingerprintFilename.c_str()); while (!file.eof()) { getline(file,fileLine); diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 725d5da9..7f3f0028 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -43,6 +43,7 @@ public: void secureConnect(); void secureAccept(); + void setFingerprintFilename(CString& f) { m_certFingerprintFilename = f; } bool isReady() const { return m_secureReady; } bool isSecureReady(); bool isSecure() { return true; } @@ -76,5 +77,5 @@ private: private: Ssl* m_ssl; bool m_secureReady; - CString m_certFingerprint; + CString m_certFingerprintFilename; }; diff --git a/src/lib/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index 7ba85752..82186b3a 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -91,7 +91,7 @@ ArgParser::parseClientArgs(ClientArgs& args, int argc, const char* const* argv) } else if (isArg(i, argc, argv, NULL, "--certificate-fingerprint", 1)) { // define scroll - args.m_certFingerprint = argv[++i]; + args.m_certFingerprintFilename = argv[++i]; } else { if (i + 1 == argc) { diff --git a/src/lib/synergy/ClientApp.cpp b/src/lib/synergy/ClientApp.cpp index b9c00414..f27a8331 100644 --- a/src/lib/synergy/ClientApp.cpp +++ b/src/lib/synergy/ClientApp.cpp @@ -342,8 +342,7 @@ ClientApp::openClient(const String& name, const NetworkAddress& address, address, new TCPSocketFactory(m_events, getSocketMultiplexer()), screen, - args().m_enableDragDrop, - args().m_enableCrypto); + args()); try { m_events->adoptHandler( diff --git a/src/lib/synergy/ClientArgs.cpp b/src/lib/synergy/ClientArgs.cpp index efbbd90b..133d5423 100644 --- a/src/lib/synergy/ClientArgs.cpp +++ b/src/lib/synergy/ClientArgs.cpp @@ -19,6 +19,6 @@ CClientArgs::CClientArgs() : m_yscroll(0), - m_certFingerprint() + m_certFingerprintFilename() { } diff --git a/src/lib/synergy/ClientArgs.h b/src/lib/synergy/ClientArgs.h index c9ddb9e9..947ca619 100644 --- a/src/lib/synergy/ClientArgs.h +++ b/src/lib/synergy/ClientArgs.h @@ -27,5 +27,5 @@ public: public: int m_yscroll; - CString m_certFingerprint; + CString m_certFingerprintFilename; }; diff --git a/src/test/integtests/net/NetworkTests.cpp b/src/test/integtests/net/NetworkTests.cpp index 7e3d3bd5..b307ff51 100644 --- a/src/test/integtests/net/NetworkTests.cpp +++ b/src/test/integtests/net/NetworkTests.cpp @@ -140,7 +140,11 @@ TEST_F(NetworkTests, sendToClient_mockData) ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); - Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, true, false); + + ClientArgs args; + args.m_enableDragDrop = true; + args.m_enableCrypto = false; + Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); m_events.adoptHandler( m_events.forIScreen().fileRecieveCompleted(), &client, @@ -192,7 +196,11 @@ TEST_F(NetworkTests, sendToClient_mockFile) ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); - Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, true, false); + + ClientArgs args; + args.m_enableDragDrop = true; + args.m_enableCrypto = false; + Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); m_events.adoptHandler( m_events.forIScreen().fileRecieveCompleted(), &client, @@ -238,7 +246,10 @@ TEST_F(NetworkTests, sendToServer_mockData) ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); - Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, true, false); + ClientArgs args; + args.m_enableDragDrop = true; + args.m_enableCrypto = false; + Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); m_events.adoptHandler( m_events.forClientListener().connected(), &listener, @@ -290,8 +301,11 @@ TEST_F(NetworkTests, sendToServer_mockFile) ON_CALL(clientScreen, getShape(_, _, _, _)).WillByDefault(Invoke(getScreenShape)); ON_CALL(clientScreen, getCursorPos(_, _)).WillByDefault(Invoke(getCursorPos)); - Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, true, false); - + ClientArgs args; + args.m_enableDragDrop = true; + args.m_enableCrypto = false; + Client client(&m_events, "stub", serverAddress, clientSocketFactory, &clientScreen, args); + m_events.adoptHandler( m_events.forClientListener().connected(), &listener, new TMethodEventJob( From 28eb85660f01163b044d1d37ce82adc62a40e383 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Tue, 14 Apr 2015 13:44:10 +0100 Subject: [PATCH 10/49] Fixed error from merge --- src/lib/base/String.cpp | 6 +++--- src/lib/base/String.h | 6 +++--- src/lib/client/Client.cpp | 4 ++-- src/lib/net/TCPSocket.h | 2 +- src/lib/plugin/ns/SecureSocket.cpp | 28 ++++++++++++++-------------- src/lib/plugin/ns/SecureSocket.h | 6 +++--- src/lib/synergy/ClientArgs.cpp | 2 +- src/lib/synergy/ClientArgs.h | 2 +- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/lib/base/String.cpp b/src/lib/base/String.cpp index 32531df8..4674deff 100644 --- a/src/lib/base/String.cpp +++ b/src/lib/base/String.cpp @@ -184,7 +184,7 @@ removeFileExt(String filename) } void -toHex(CString& subject, int width, const char fill) +toHex(String& subject, int width, const char fill) { std::stringstream ss; ss << std::hex; @@ -196,13 +196,13 @@ toHex(CString& subject, int width, const char fill) } void -uppercase(CString& subject) +uppercase(String& subject) { std::transform(subject.begin(), subject.end(), subject.begin(), ::toupper); } void -removeChar(CString& subject, const char c) +removeChar(String& subject, const char c) { subject.erase(std::remove(subject.begin(), subject.end(), c), subject.end()); } diff --git a/src/lib/base/String.h b/src/lib/base/String.h index 57f3c69c..dbe5c21b 100644 --- a/src/lib/base/String.h +++ b/src/lib/base/String.h @@ -74,19 +74,19 @@ String removeFileExt(String filename); /*! Convert each character in \c subject into hexdecimal form with \c width */ -void toHex(CString& subject, int width, const char fill = '0'); +void toHex(String& subject, int width, const char fill = '0'); //! Convert to all uppercase /*! Convert each character in \c subject to uppercase */ -void uppercase(CString& subject); +void uppercase(String& subject); //! Remove all specific char in suject /*! Remove all specific \c char in \c suject */ -void removeChar(CString& subject, const char c); +void removeChar(String& subject, const char c); //! Case-insensitive comparisons diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 43717134..329733d4 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -77,7 +77,7 @@ Client::Client( m_sendFileThread(NULL), m_writeToDropDirThread(NULL), m_socket(NULL), - m_useSecureNetwork(false) + m_useSecureNetwork(false), m_args(args) { assert(m_socketFactory != NULL); @@ -104,7 +104,7 @@ Client::Client( &Client::handleFileRecieveCompleted)); } - if (enableCrypto) { + if (m_args.m_enableCrypto) { m_useSecureNetwork = ARCH->plugin().exists(s_networkSecurity); if (m_useSecureNetwork == false) { LOG((CLOG_NOTE "crypto disabled because of ns plugin not available")); diff --git a/src/lib/net/TCPSocket.h b/src/lib/net/TCPSocket.h index 57bb0169..2e75f357 100644 --- a/src/lib/net/TCPSocket.h +++ b/src/lib/net/TCPSocket.h @@ -59,7 +59,7 @@ public: virtual void secureConnect() {} virtual void secureAccept() {} - virtual void setFingerprintFilename(CString& f) {} + virtual void setFingerprintFilename(String& f) {} protected: ArchSocket getSocket() { return m_socket; } diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index de63e333..d1af5b85 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -41,10 +41,10 @@ struct Ssl { SSL* m_ssl; }; -CSecureSocket::CSecureSocket( +SecureSocket::SecureSocket( IEventQueue* events, - CSocketMultiplexer* socketMultiplexer) : - CTCPSocket(events, socketMultiplexer), + SocketMultiplexer* socketMultiplexer) : + TCPSocket(events, socketMultiplexer), m_secureReady(false), m_certFingerprintFilename() { @@ -396,14 +396,14 @@ SecureSocket::getError() } void -CSecureSocket::disconnect() +SecureSocket::disconnect() { sendEvent(getEvents()->forISocket().disconnected()); sendEvent(getEvents()->forIStream().inputShutdown()); } bool -CSecureSocket::verifyCertFingerprint() +SecureSocket::verifyCertFingerprint() { if (m_certFingerprintFilename.empty()) { return false; @@ -420,15 +420,15 @@ CSecureSocket::verifyCertFingerprint() } // convert fingerprint into hexdecimal format - CString fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); + String fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); synergy::string::toHex(fingerprint, 2); // all uppercase synergy::string::uppercase(fingerprint); // check if this fingerprint exist - CString fileLine; - CString certificateFingerprint; + String fileLine; + String certificateFingerprint; std::ifstream file; file.open(m_certFingerprintFilename.c_str()); @@ -437,14 +437,14 @@ CSecureSocket::verifyCertFingerprint() // example of a fingerprint: // SHA1 Fingerprint=6E:41:1A:21:53:2E:A3:EF:4D:A6:F2:A6:BA:0E:27:09:8A:F3:A1:10 size_t found = fileLine.find('='); - if (found != CString::npos) { + if (found != String::npos) { certificateFingerprint = fileLine.substr(found + 1); if (!certificateFingerprint.empty()) { // remove colons synergy::string::removeChar(certificateFingerprint, ':'); - if(certificateFingerprint.compare(fingerprint) == 0) { + if (certificateFingerprint.compare(fingerprint) == 0) { file.close(); return true; } @@ -458,10 +458,10 @@ CSecureSocket::verifyCertFingerprint() } ISocketMultiplexerJob* -CSecureSocket::serviceConnect(ISocketMultiplexerJob* job, +SecureSocket::serviceConnect(ISocketMultiplexerJob* job, bool, bool write, bool error) { - CLock lock(&getMutex()); + Lock lock(&getMutex()); bool retry = true; #ifdef SYSAPI_WIN32 @@ -474,10 +474,10 @@ CSecureSocket::serviceConnect(ISocketMultiplexerJob* job, } ISocketMultiplexerJob* -CSecureSocket::serviceAccept(ISocketMultiplexerJob* job, +SecureSocket::serviceAccept(ISocketMultiplexerJob* job, bool, bool write, bool error) { - CLock lock(&getMutex()); + Lock lock(&getMutex()); bool retry = true; #ifdef SYSAPI_WIN32 diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 7f3f0028..50ca17b6 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -43,7 +43,7 @@ public: void secureConnect(); void secureAccept(); - void setFingerprintFilename(CString& f) { m_certFingerprintFilename = f; } + void setFingerprintFilename(String& f) { m_certFingerprintFilename = f; } bool isReady() const { return m_secureReady; } bool isSecureReady(); bool isSecure() { return true; } @@ -62,7 +62,7 @@ private: void checkResult(int n, bool& fatal, bool& retry); void showError(); void throwError(const char* reason); - CString getError(); + String getError(); void disconnect(); bool verifyCertFingerprint(); @@ -77,5 +77,5 @@ private: private: Ssl* m_ssl; bool m_secureReady; - CString m_certFingerprintFilename; + String m_certFingerprintFilename; }; diff --git a/src/lib/synergy/ClientArgs.cpp b/src/lib/synergy/ClientArgs.cpp index 133d5423..fff34817 100644 --- a/src/lib/synergy/ClientArgs.cpp +++ b/src/lib/synergy/ClientArgs.cpp @@ -17,7 +17,7 @@ #include "synergy/ClientArgs.h" -CClientArgs::CClientArgs() : +ClientArgs::ClientArgs() : m_yscroll(0), m_certFingerprintFilename() { diff --git a/src/lib/synergy/ClientArgs.h b/src/lib/synergy/ClientArgs.h index 947ca619..093b0ccf 100644 --- a/src/lib/synergy/ClientArgs.h +++ b/src/lib/synergy/ClientArgs.h @@ -27,5 +27,5 @@ public: public: int m_yscroll; - CString m_certFingerprintFilename; + String m_certFingerprintFilename; }; From dd574c4f2ca1f505ff02106f88fe375c537ae1f4 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Tue, 14 Apr 2015 13:47:34 +0100 Subject: [PATCH 11/49] Added unit tests for string operations --- src/test/unittests/base/StringTests.cpp | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/test/unittests/base/StringTests.cpp b/src/test/unittests/base/StringTests.cpp index e0108413..2a461f05 100644 --- a/src/test/unittests/base/StringTests.cpp +++ b/src/test/unittests/base/StringTests.cpp @@ -53,3 +53,32 @@ TEST(StringTests, sprintf) EXPECT_EQ("answer=42", result); } + +TEST(StringTests, toHex) +{ + String subject = "foobar"; + int width = 2; + + string::toHex(subject, width); + + EXPECT_EQ("666f6f626172", subject); +} + +TEST(StringTests, uppercase) +{ + String subject = "12foo3BaR"; + + string::uppercase(subject); + + EXPECT_EQ("12FOO3BAR", subject); +} + +TEST(StringTests, removeChar) +{ + String subject = "foobar"; + const char c = 'o'; + + string::removeChar(subject, c); + + EXPECT_EQ("fbar", subject); +} From 916a4c75af19f9d6031c7236d63b308f943250fc Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Fri, 10 Apr 2015 14:07:53 +0100 Subject: [PATCH 12/49] Refactored no or wrong ssl certificate error handling #4410 Conflicts: src/lib/net/TCPListenSocket.cpp src/lib/plugin/ns/SecureListenSocket.cpp src/lib/plugin/ns/SecureSocket.cpp src/lib/plugin/ns/SecureSocket.h --- src/lib/mt/Thread.cpp | 5 -- src/lib/net/TCPListenSocket.cpp | 16 +++-- src/lib/net/TCPListenSocket.h | 3 + src/lib/plugin/ns/SecureListenSocket.cpp | 19 +++++- src/lib/plugin/ns/SecureSocket.cpp | 75 +++++++++++++++--------- src/lib/plugin/ns/SecureSocket.h | 7 +-- 6 files changed, 83 insertions(+), 42 deletions(-) diff --git a/src/lib/mt/Thread.cpp b/src/lib/mt/Thread.cpp index d77d0705..f28bb6b9 100644 --- a/src/lib/mt/Thread.cpp +++ b/src/lib/mt/Thread.cpp @@ -18,7 +18,6 @@ #include "mt/Thread.h" -#include "net/XSocket.h" #include "mt/XMT.h" #include "mt/XThread.h" #include "arch/Arch.h" @@ -158,10 +157,6 @@ Thread::threadFunc(void* vjob) job->run(); LOG((CLOG_DEBUG1 "thread 0x%08x exit", id)); } - - catch (XSocket& e) { - LOG((CLOG_DEBUG "%s", e.what())); - } catch (XThreadCancel&) { // client called cancel() LOG((CLOG_DEBUG1 "caught cancel on thread 0x%08x", id)); diff --git a/src/lib/net/TCPListenSocket.cpp b/src/lib/net/TCPListenSocket.cpp index cdbd73c4..38d4dd8c 100644 --- a/src/lib/net/TCPListenSocket.cpp +++ b/src/lib/net/TCPListenSocket.cpp @@ -112,27 +112,35 @@ TCPListenSocket::accept() try { socket = new TCPSocket(m_events, m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL)); if (socket != NULL) { - m_socketMultiplexer->addSocket(this, - new TSocketMultiplexerMethodJob( - this, &TCPListenSocket::serviceListening, - m_socket, true, false)); + setListeningJob(); } return socket; } catch (XArchNetwork&) { if (socket != NULL) { delete socket; + setListeningJob(); } return NULL; } catch (std::exception &ex) { if (socket != NULL) { delete socket; + setListeningJob(); } throw ex; } } +void +CTCPListenSocket::setListeningJob() +{ + m_socketMultiplexer->addSocket(this, + new TSocketMultiplexerMethodJob( + this, &CTCPListenSocket::serviceListening, + m_socket, true, false)); +} + ISocketMultiplexerJob* TCPListenSocket::serviceListening(ISocketMultiplexerJob* job, bool read, bool, bool error) diff --git a/src/lib/net/TCPListenSocket.h b/src/lib/net/TCPListenSocket.h index ef2687db..c769e170 100644 --- a/src/lib/net/TCPListenSocket.h +++ b/src/lib/net/TCPListenSocket.h @@ -45,6 +45,9 @@ public: accept(); virtual void deleteSocket(void*) { } +protected: + void setListeningJob(); + public: ISocketMultiplexerJob* serviceListening(ISocketMultiplexerJob*, diff --git a/src/lib/plugin/ns/SecureListenSocket.cpp b/src/lib/plugin/ns/SecureListenSocket.cpp index a0df2519..bee4b29d 100644 --- a/src/lib/plugin/ns/SecureListenSocket.cpp +++ b/src/lib/plugin/ns/SecureListenSocket.cpp @@ -55,9 +55,16 @@ SecureListenSocket::accept() m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL)); +<<<<<<< HEAD:src/lib/plugin/ns/SecureListenSocket.cpp m_secureSocketSet.insert(socket); socket->initSsl(true); +======= + if (socket != NULL) { + setListeningJob(); + } + +>>>>>>> 79b9c52... Refactored no or wrong ssl certificate error handling #30:src/lib/net/SecureListenSocket.cpp // TODO: customized certificate path String certificateFilename = ARCH->getProfileDirectory(); #if SYSAPI_WIN32 @@ -67,26 +74,36 @@ SecureListenSocket::accept() #endif certificateFilename.append(s_certificateFilename); - socket->loadCertificates(certificateFilename.c_str()); + bool loaded = socket->loadCertificates(certificateFilename); + if (!loaded) { + delete socket; + return NULL; + } + socket->secureAccept(); +<<<<<<< HEAD:src/lib/plugin/ns/SecureListenSocket.cpp if (socket != NULL) { m_socketMultiplexer->addSocket(this, new TSocketMultiplexerMethodJob( this, &TCPListenSocket::serviceListening, m_socket, true, false)); } +======= +>>>>>>> 79b9c52... Refactored no or wrong ssl certificate error handling #30:src/lib/net/SecureListenSocket.cpp return dynamic_cast(socket); } catch (XArchNetwork&) { if (socket != NULL) { delete socket; + setListeningJob(); } return NULL; } catch (std::exception &ex) { if (socket != NULL) { delete socket; + setListeningJob(); } throw ex; } diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index d1af5b85..1be5f184 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -151,24 +151,46 @@ SecureSocket::initSsl(bool server) initContext(server); } -void -SecureSocket::loadCertificates(const char* filename) +bool +CSecureSocket::loadCertificates(CString& filename) { - int r = 0; - r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM); - if (r <= 0) { - throwError("could not use ssl certificate"); + if (filename.empty()) { + showError("ssl certificate is not specified"); + return false; + } + else { + std::ifstream file(filename.c_str()); + bool exist = file.good(); + file.close(); + + if (!exist) { + CString errorMsg("ssl certificate doesn't exist: "); + errorMsg.append(filename); + showError(errorMsg.c_str()); + return false; + } } - r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM); + int r = 0; + r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename.c_str(), SSL_FILETYPE_PEM); if (r <= 0) { - throwError("could not use ssl private key"); + showError("could not use ssl certificate"); + return false; + } + + r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, filename.c_str(), SSL_FILETYPE_PEM); + if (r <= 0) { + showError("could not use ssl private key"); + return false; } r = SSL_CTX_check_private_key(m_ssl->m_context); if (!r) { - throwError("could not verify ssl private key"); + showError("could not verify ssl private key"); + return false; } + + return true; } void @@ -258,7 +280,8 @@ SecureSocket::secureConnect(int socket) // tell user and sleep so the socket isn't hammered. LOG((CLOG_ERR "failed to connect secure socket")); LOG((CLOG_INFO "server connection may not be secure")); - ARCH->sleep(1); + disconnect(); + return false; } m_secureReady = !retry; @@ -266,7 +289,9 @@ SecureSocket::secureConnect(int socket) if (m_secureReady) { if (verifyCertFingerprint()) { LOG((CLOG_INFO "connected to secure socket")); - showCertificate(); + if (!showCertificate()) { + disconnect(); + } } else { LOG((CLOG_ERR "failed to verity server certificate fingerprint")); @@ -277,8 +302,8 @@ SecureSocket::secureConnect(int socket) return retry; } -void -SecureSocket::showCertificate() +bool +CSecureSocket::showCertificate() { X509* cert; char* line; @@ -292,8 +317,11 @@ SecureSocket::showCertificate() X509_free(cert); } else { - throwError("server has no ssl certificate"); + showError("server has no ssl certificate"); + return false; } + + return true; } void @@ -359,24 +387,15 @@ SecureSocket::checkResult(int n, bool& fatal, bool& retry) } void -SecureSocket::showError() +CSecureSocket::showError(const char* reason) { - String error = getError(); - if (!error.empty()) { - LOG((CLOG_ERR "secure socket error: %s", error.c_str())); + if (reason != NULL) { + LOG((CLOG_ERR "%s", reason)); } -} -void -SecureSocket::throwError(const char* reason) -{ - String error = getError(); + CString error = getError(); if (!error.empty()) { - throw XSocket(synergy::string::sprintf( - "%s: %s", reason, error.c_str())); - } - else { - throw XSocket(reason); + LOG((CLOG_ERR "%s", error.c_str())); } } diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 50ca17b6..4f5e5d70 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -50,7 +50,7 @@ public: UInt32 secureRead(void* buffer, UInt32 n); UInt32 secureWrite(const void* buffer, UInt32 n); void initSsl(bool server); - void loadCertificates(const char* CertFile); + bool loadCertificates(CString& CertFile); private: // SSL @@ -58,10 +58,9 @@ private: void createSSL(); bool secureAccept(int s); bool secureConnect(int s); - void showCertificate(); + bool showCertificate(); void checkResult(int n, bool& fatal, bool& retry); - void showError(); - void throwError(const char* reason); + void showError(const char* reason = NULL); String getError(); void disconnect(); bool verifyCertFingerprint(); From f60e98c8cd1c6810acfb749f86cf1d53fdd502ca Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Tue, 14 Apr 2015 14:03:43 +0100 Subject: [PATCH 13/49] Fixed error from merge --- src/lib/net/TCPListenSocket.cpp | 6 +++--- src/lib/plugin/ns/SecureListenSocket.cpp | 15 +-------------- src/lib/plugin/ns/SecureSocket.cpp | 10 +++++----- src/lib/plugin/ns/SecureSocket.h | 2 +- 4 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/lib/net/TCPListenSocket.cpp b/src/lib/net/TCPListenSocket.cpp index 38d4dd8c..f0f06ee3 100644 --- a/src/lib/net/TCPListenSocket.cpp +++ b/src/lib/net/TCPListenSocket.cpp @@ -133,11 +133,11 @@ TCPListenSocket::accept() } void -CTCPListenSocket::setListeningJob() +TCPListenSocket::setListeningJob() { m_socketMultiplexer->addSocket(this, - new TSocketMultiplexerMethodJob( - this, &CTCPListenSocket::serviceListening, + new TSocketMultiplexerMethodJob( + this, &TCPListenSocket::serviceListening, m_socket, true, false)); } diff --git a/src/lib/plugin/ns/SecureListenSocket.cpp b/src/lib/plugin/ns/SecureListenSocket.cpp index bee4b29d..562a6899 100644 --- a/src/lib/plugin/ns/SecureListenSocket.cpp +++ b/src/lib/plugin/ns/SecureListenSocket.cpp @@ -54,17 +54,13 @@ SecureListenSocket::accept() m_events, m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL)); - -<<<<<<< HEAD:src/lib/plugin/ns/SecureListenSocket.cpp + socket->initSsl(true); m_secureSocketSet.insert(socket); - socket->initSsl(true); -======= if (socket != NULL) { setListeningJob(); } ->>>>>>> 79b9c52... Refactored no or wrong ssl certificate error handling #30:src/lib/net/SecureListenSocket.cpp // TODO: customized certificate path String certificateFilename = ARCH->getProfileDirectory(); #if SYSAPI_WIN32 @@ -82,15 +78,6 @@ SecureListenSocket::accept() socket->secureAccept(); -<<<<<<< HEAD:src/lib/plugin/ns/SecureListenSocket.cpp - if (socket != NULL) { - m_socketMultiplexer->addSocket(this, - new TSocketMultiplexerMethodJob( - this, &TCPListenSocket::serviceListening, - m_socket, true, false)); - } -======= ->>>>>>> 79b9c52... Refactored no or wrong ssl certificate error handling #30:src/lib/net/SecureListenSocket.cpp return dynamic_cast(socket); } catch (XArchNetwork&) { diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 1be5f184..64d013d1 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -152,7 +152,7 @@ SecureSocket::initSsl(bool server) } bool -CSecureSocket::loadCertificates(CString& filename) +SecureSocket::loadCertificates(String& filename) { if (filename.empty()) { showError("ssl certificate is not specified"); @@ -164,7 +164,7 @@ CSecureSocket::loadCertificates(CString& filename) file.close(); if (!exist) { - CString errorMsg("ssl certificate doesn't exist: "); + String errorMsg("ssl certificate doesn't exist: "); errorMsg.append(filename); showError(errorMsg.c_str()); return false; @@ -303,7 +303,7 @@ SecureSocket::secureConnect(int socket) } bool -CSecureSocket::showCertificate() +SecureSocket::showCertificate() { X509* cert; char* line; @@ -387,13 +387,13 @@ SecureSocket::checkResult(int n, bool& fatal, bool& retry) } void -CSecureSocket::showError(const char* reason) +SecureSocket::showError(const char* reason) { if (reason != NULL) { LOG((CLOG_ERR "%s", reason)); } - CString error = getError(); + String error = getError(); if (!error.empty()) { LOG((CLOG_ERR "%s", error.c_str())); } diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 4f5e5d70..cff4c34f 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -50,7 +50,7 @@ public: UInt32 secureRead(void* buffer, UInt32 n); UInt32 secureWrite(const void* buffer, UInt32 n); void initSsl(bool server); - bool loadCertificates(CString& CertFile); + bool loadCertificates(String& CertFile); private: // SSL From fa1ea0022b1d61b919d1a50e9893f9a950132125 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Tue, 14 Apr 2015 14:04:54 +0100 Subject: [PATCH 14/49] Fixed code style --- src/lib/synergy/ArgsBase.h | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/lib/synergy/ArgsBase.h b/src/lib/synergy/ArgsBase.h index 125f9b51..743202e8 100644 --- a/src/lib/synergy/ArgsBase.h +++ b/src/lib/synergy/ArgsBase.h @@ -24,25 +24,27 @@ class ArgsBase { public: ArgsBase(); virtual ~ArgsBase(); - bool m_daemon; - bool m_backend; - bool m_restartable; - bool m_noHooks; - const char* m_pname; - const char* m_logFilter; - const char* m_logFile; - const char* m_display; - String m_name; - bool m_disableTray; - bool m_enableIpc; - bool m_enableDragDrop; + +public: + bool m_daemon; + bool m_backend; + bool m_restartable; + bool m_noHooks; + const char* m_pname; + const char* m_logFilter; + const char* m_logFile; + const char* m_display; + String m_name; + bool m_disableTray; + bool m_enableIpc; + bool m_enableDragDrop; #if SYSAPI_WIN32 - bool m_debugServiceWait; - bool m_pauseOnExit; - bool m_stopOnDeskSwitch; + bool m_debugServiceWait; + bool m_pauseOnExit; + bool m_stopOnDeskSwitch; #endif #if WINAPI_XWINDOWS - bool m_disableXInitThreads; + bool m_disableXInitThreads; #endif bool m_shouldExit; String m_synergyAddress; From 1e2b822226a5c88c31ce742065a4c764e575630e Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Tue, 14 Apr 2015 14:28:32 +0100 Subject: [PATCH 15/49] Removed unused variable --- src/lib/client/Client.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/client/Client.h b/src/lib/client/Client.h index 12baadb4..e50b567b 100644 --- a/src/lib/client/Client.h +++ b/src/lib/client/Client.h @@ -224,7 +224,6 @@ private: String m_dragFileExt; Thread* m_sendFileThread; Thread* m_writeToDropDirThread; - bool m_enableDragDrop; TCPSocket* m_socket; bool m_useSecureNetwork; ClientArgs m_args; From 52d9b1beedd24ebaeaa39455253593e8e267ae6e Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Wed, 15 Apr 2015 13:06:49 +0100 Subject: [PATCH 16/49] Logged out new fingerprint when not match #4522 --- src/lib/plugin/ns/SecureSocket.cpp | 50 ++++++++++++++++++------------ src/lib/plugin/ns/SecureSocket.h | 3 ++ 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 64d013d1..22815cce 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -421,6 +421,26 @@ SecureSocket::disconnect() sendEvent(getEvents()->forIStream().inputShutdown()); } +void +SecureSocket::formatFingerprint(String& fingerprint, bool hex, bool separator) +{ + if (hex) { + // to hexidecimal + synergy::string::toHex(fingerprint, 2); + } + + // all uppercase + synergy::string::uppercase(fingerprint); + + if (separator) { + // add colon to separate each 2 charactors + size_t separators = fingerprint.size() / 2; + for (size_t i = 1; i < separators; i++) { + fingerprint.insert(i * 3 - 1, ":"); + } + } +} + bool SecureSocket::verifyCertFingerprint() { @@ -438,41 +458,31 @@ SecureSocket::verifyCertFingerprint() return false; } - // convert fingerprint into hexdecimal format + // format fingerprint into hexdecimal format with colon separator String fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); - synergy::string::toHex(fingerprint, 2); - - // all uppercase - synergy::string::uppercase(fingerprint); + formatFingerprint(fingerprint); // check if this fingerprint exist String fileLine; - String certificateFingerprint; std::ifstream file; file.open(m_certFingerprintFilename.c_str()); while (!file.eof()) { getline(file,fileLine); - // example of a fingerprint: - // SHA1 Fingerprint=6E:41:1A:21:53:2E:A3:EF:4D:A6:F2:A6:BA:0E:27:09:8A:F3:A1:10 - size_t found = fileLine.find('='); - if (found != String::npos) { - certificateFingerprint = fileLine.substr(found + 1); - - if (!certificateFingerprint.empty()) { - // remove colons - synergy::string::removeChar(certificateFingerprint, ':'); - - if (certificateFingerprint.compare(fingerprint) == 0) { - file.close(); - return true; - } + // example of a fingerprint:A1:B2:C3 + if (!fileLine.empty()) { + if (fileLine.compare(fingerprint) == 0) { + file.close(); + return true; } } } file.close(); + LOG((CLOG_NOTE "new fingerprint from a server")); + LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str())); + return false; } diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index cff4c34f..1bc64628 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -63,6 +63,9 @@ private: void showError(const char* reason = NULL); String getError(); void disconnect(); + void formatFingerprint(String& fingerprint, + bool hex = true, + bool separator = true); bool verifyCertFingerprint(); ISocketMultiplexerJob* From 689737ee7a5317f89c1f11f36f66ccc086ef3534 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 15 Apr 2015 13:09:22 +0100 Subject: [PATCH 17/49] Fingerprint file check and trust logic #4522 Also refactored the 'get profile dir' code to use the core interface (reduce code duplication) --- src/gui/gui.pro | 6 ++- src/gui/src/Fingerprint.cpp | 104 ++++++++++++++++++++++++++++++++++++ src/gui/src/Fingerprint.h | 38 +++++++++++++ src/gui/src/MainWindow.cpp | 94 ++++++++++++++++++-------------- src/gui/src/MainWindow.h | 4 +- 5 files changed, 202 insertions(+), 44 deletions(-) create mode 100644 src/gui/src/Fingerprint.cpp create mode 100644 src/gui/src/Fingerprint.h diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 4f8fcabb..7f2670be 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -55,7 +55,8 @@ SOURCES += src/main.cpp \ src/WebClient.cpp \ src/PluginWizardPage.cpp \ src/PluginManager.cpp \ - src/CoreInterface.cpp + src/CoreInterface.cpp \ + src/Fingerprint.cpp HEADERS += src/MainWindow.h \ src/AboutDialog.h \ src/ServerConfig.h \ @@ -97,7 +98,8 @@ HEADERS += src/MainWindow.h \ src/PluginWizardPage.h \ src/ProcessorArch.h \ src/PluginManager.h \ - src/CoreInterface.h + src/CoreInterface.h \ + src/Fingerprint.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc macx { diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp new file mode 100644 index 00000000..0ff15a44 --- /dev/null +++ b/src/gui/src/Fingerprint.cpp @@ -0,0 +1,104 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "Fingerprint.h" + +#include "CoreInterface.h" + +#include +#include + +static const char kDirName[] = "ssl/fingerprints"; +static const char kLocalFilename[] = "local.txt"; +static const char kTrustedServersFilename[] = "trusted-servers.txt"; +static const char kTrustedClientsFilename[] = "trusted-clients.txt"; + +Fingerprint::Fingerprint(const QString& filename) +{ + m_Filename = filename; +} + +void Fingerprint::trust(const QString& fingerprintText) +{ + CoreInterface coreInterface; + QString profileDir = coreInterface.getProfileDir(); + + QString dirName = QString("%1/%2") + .arg(profileDir) + .arg(kDirName); + + QDir dir(dirName); + if (!dir.exists()) { + dir.mkpath("."); + } + + QString path = QString("%1/%2").arg(dirName).arg(m_Filename); + QFile file(path); + if (file.open(QIODevice::Append)) + { + QTextStream out(&file); + out << fingerprintText << "\n"; + file.close(); + } +} + +bool Fingerprint::check(const QString& fingerprintText) +{ + CoreInterface coreInterface; + QString profileDir = coreInterface.getProfileDir(); + + QString dirName = QString("%1/%2") + .arg(profileDir) + .arg(kDirName); + + if (!QDir(dirName).exists()) { + return false; + } + + QString path = QString("%1/%2").arg(dirName).arg(m_Filename); + QFile file(path); + + if (file.open(QIODevice::ReadOnly)) + { + QTextStream in(&file); + while (!in.atEnd()) + { + QString trusted = in.readLine(); + if (fingerprintText == trusted) { + return true; + } + } + file.close(); + } + + return false; +} + +Fingerprint Fingerprint::local() +{ + return Fingerprint(kLocalFilename); +} + +Fingerprint Fingerprint::trustedServers() +{ + return Fingerprint(kTrustedServersFilename); +} + +Fingerprint Fingerprint::trustedClients() +{ + return Fingerprint(kTrustedClientsFilename); +} diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h new file mode 100644 index 00000000..d494af0b --- /dev/null +++ b/src/gui/src/Fingerprint.h @@ -0,0 +1,38 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +class Fingerprint +{ +private: + Fingerprint(const QString& filename); + +public: + void trust(const QString& fingerprintText); + bool check(const QString& fingerprintText); + +public: + static Fingerprint local(); + static Fingerprint trustedServers(); + static Fingerprint trustedClients(); + +private: + QString m_Filename; +}; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 234370ed..c4e8b0fc 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -21,6 +21,8 @@ #include #include "MainWindow.h" + +#include "Fingerprint.h" #include "AboutDialog.h" #include "ServerConfigDialog.h" #include "SettingsDialog.h" @@ -396,32 +398,48 @@ void MainWindow::updateStateFromLogLine(const QString &line) setSynergyState(synergyConnected); } + checkFingerprint(line); +} + +void MainWindow::checkFingerprint(const QString& line) +{ QRegExp fingerprintRegex(".*server fingerprint: ([A-F0-9:]+)"); - if (fingerprintRegex.exactMatch(line)) { + if (!fingerprintRegex.exactMatch(line)) { + return; + } - QString fingerprint = fingerprintRegex.cap(1); - QMessageBox::StandardButton fingerprintReply = - QMessageBox::information( - this, tr("Security question"), - tr("Do you trust this fingerprint?\n\n" - "%1\n\n" - "This is a server fingerprint. You should compare this " - "fingerprint to the one on your server's screen. If the " - "two don't match exactly, then it's probably not the server " - "you're expecting (it could be a malicious user).\n\n" - "To automatically trust this fingerprint for future " - "connections, click Yes. To reject this fingerprint and " - "disconnect from the server, click No.") - .arg(fingerprint), - QMessageBox::Yes | QMessageBox::No); + QString fingerprint = fingerprintRegex.cap(1); + if (Fingerprint::trustedServers().check(fingerprint)) { + return; + } - if (fingerprintReply == QMessageBox::Yes) { - // TODO: save to file - qDebug() << "fingerprint: " << fingerprint; - } - else { - stopSynergy(); - } + QMessageBox::StandardButton fingerprintReply = + QMessageBox::information( + this, tr("Security question"), + tr("Do you trust this fingerprint?\n\n" + "%1\n\n" + "This is a server fingerprint. You should compare this " + "fingerprint to the one on your server's screen. If the " + "two don't match exactly, then it's probably not the server " + "you're expecting (it could be a malicious user).\n\n" + "To automatically trust this fingerprint for future " + "connections, click Yes. To reject this fingerprint and " + "disconnect from the server, click No.") + .arg(fingerprint), + QMessageBox::Yes | QMessageBox::No); + + if (fingerprintReply == QMessageBox::Yes) { + // restart core process after trusting fingerprint. + Fingerprint::trustedServers().trust(fingerprint); + startSynergy(); + } + else { + // on all platforms, the core process will stop if the + // fingerprint is not trusted, so technically the stop + // isn't really needed. however on windows, the core + // process will keep trying (and failing) unless we + // tell it to stop. + stopSynergy(); } } @@ -479,7 +497,11 @@ void MainWindow::startSynergy() } #if defined(Q_OS_WIN) - args << "--profile-dir" << getProfileDirectoryForArg(); + // on windows, the profile directory changes depending on the user that + // launched the process (e.g. when launched with elevation). setting the + // profile dir on launch ensures it uses the same profile dir is used + // no matter how its relaunched. + args << "--profile-dir" << getProfileRootForArg(); #endif if ((synergyType() == synergyClient && !clientArgs(args, app)) @@ -1251,25 +1273,17 @@ void MainWindow::bonjourInstallFinished() m_pCheckBoxAutoConfig->setChecked(true); } -QString MainWindow::getProfileDirectory() +QString MainWindow::getProfileRootForArg() { + CoreInterface coreInterface; + QString dir = coreInterface.getProfileDir(); + + // HACK: strip our app name since we're returning the root dir. #if defined(Q_OS_WIN) - - QString qtDataDir = QDesktopServices::storageLocation( - QDesktopServices::DataLocation); - - // HACK: core wants the base app data dir, this seems like a very hacky - // way to get it (maybe consider using %LOCALAPPDATA% instead?) - return qtDataDir.replace("\\Synergy\\Synergy", ""); - + dir.replace("\\Synergy", ""); #else - - return ""; - + dir.replace("/.synergy", ""); #endif -} -QString MainWindow::getProfileDirectoryForArg() -{ - return QString("\"%1\"").arg(getProfileDirectory()); + return QString("\"%1\"").arg(dir); } diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index b82984cf..9ab1b17b 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -165,8 +165,8 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void downloadBonjour(); void promptAutoConfig(); void updateEdition(); - QString getProfileDirectory(); - QString getProfileDirectoryForArg(); + QString getProfileRootForArg(); + void checkFingerprint(const QString& line); private: QSettings& m_Settings; From e405ec25e30b2187bb6ada867b87f16e9454ef0b Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Wed, 15 Apr 2015 13:25:18 +0100 Subject: [PATCH 18/49] Always log out server fingerprint #4522 --- src/lib/plugin/ns/SecureSocket.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 22815cce..7f78554c 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -461,29 +461,27 @@ SecureSocket::verifyCertFingerprint() // format fingerprint into hexdecimal format with colon separator String fingerprint(reinterpret_cast(tempFingerprint), tempFingerprintLen); formatFingerprint(fingerprint); + LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str())); // check if this fingerprint exist String fileLine; std::ifstream file; file.open(m_certFingerprintFilename.c_str()); + bool isValid = false; while (!file.eof()) { getline(file,fileLine); // example of a fingerprint:A1:B2:C3 if (!fileLine.empty()) { if (fileLine.compare(fingerprint) == 0) { - file.close(); - return true; + isValid = true; + break; } } } file.close(); - - LOG((CLOG_NOTE "new fingerprint from a server")); - LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str())); - - return false; + return isValid; } ISocketMultiplexerJob* From 407f92e9d4f3a36931168f0cee937591d79b00aa Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 15 Apr 2015 14:16:28 +0100 Subject: [PATCH 19/49] Removed --certificate-fingerprint argument #4522 Used profile dir for fingerprint file path instead --- src/lib/client/Client.cpp | 1 - src/lib/plugin/ns/SecureSocket.cpp | 29 +++++++++++++++++++---------- src/lib/plugin/ns/SecureSocket.h | 2 -- src/lib/synergy/ArgParser.cpp | 4 ---- src/lib/synergy/ClientArgs.cpp | 3 +-- src/lib/synergy/ClientArgs.h | 1 - 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 329733d4..9c7d785d 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -161,7 +161,6 @@ Client::connect() // create the socket IDataSocket* socket = m_socketFactory->create(m_useSecureNetwork); m_socket = dynamic_cast(socket); - m_socket->setFingerprintFilename(m_args.m_certFingerprintFilename); // filter socket messages, including a packetizing filter m_stream = socket; diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 7f78554c..7de15eff 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -36,6 +36,11 @@ #define MAX_ERROR_SIZE 65535 +static const char kFingerprintDirName[] = "ssl/fingerprints"; +static const char kFingerprintLocalFilename[] = "local.txt"; +static const char kFingerprintTrustedServersFilename[] = "trusted-servers.txt"; +static const char kFingerprintTrustedClientsFilename[] = "trusted-clients.txt"; + struct Ssl { SSL_CTX* m_context; SSL* m_ssl; @@ -45,8 +50,7 @@ SecureSocket::SecureSocket( IEventQueue* events, SocketMultiplexer* socketMultiplexer) : TCPSocket(events, socketMultiplexer), - m_secureReady(false), - m_certFingerprintFilename() + m_secureReady(false) { } @@ -294,7 +298,7 @@ SecureSocket::secureConnect(int socket) } } else { - LOG((CLOG_ERR "failed to verity server certificate fingerprint")); + LOG((CLOG_ERR "failed to verify server certificate fingerprint")); disconnect(); } } @@ -444,17 +448,16 @@ SecureSocket::formatFingerprint(String& fingerprint, bool hex, bool separator) bool SecureSocket::verifyCertFingerprint() { - if (m_certFingerprintFilename.empty()) { - return false; - } - // calculate received certificate fingerprint X509 *cert = cert = SSL_get_peer_certificate(m_ssl->m_ssl); EVP_MD* tempDigest; unsigned char tempFingerprint[EVP_MAX_MD_SIZE]; unsigned int tempFingerprintLen; tempDigest = (EVP_MD*)EVP_sha1(); - if (X509_digest(cert, tempDigest, tempFingerprint, &tempFingerprintLen) <= 0) { + int digestResult = X509_digest(cert, tempDigest, tempFingerprint, &tempFingerprintLen); + + if (digestResult <= 0) { + LOG((CLOG_ERR "failed to calculate fingerprint, digest result: %d", digestResult)); return false; } @@ -463,15 +466,21 @@ SecureSocket::verifyCertFingerprint() formatFingerprint(fingerprint); LOG((CLOG_NOTE "server fingerprint: %s", fingerprint.c_str())); + String trustedServersFilename; + trustedServersFilename = synergy::string::sprintf( + "%s/%s/%s", + ARCH->getProfileDirectory().c_str(), + kFingerprintDirName, + kFingerprintTrustedServersFilename); + // check if this fingerprint exist String fileLine; std::ifstream file; - file.open(m_certFingerprintFilename.c_str()); + file.open(trustedServersFilename.c_str()); bool isValid = false; while (!file.eof()) { getline(file,fileLine); - // example of a fingerprint:A1:B2:C3 if (!fileLine.empty()) { if (fileLine.compare(fingerprint) == 0) { isValid = true; diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 1bc64628..1fa03c47 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -43,7 +43,6 @@ public: void secureConnect(); void secureAccept(); - void setFingerprintFilename(String& f) { m_certFingerprintFilename = f; } bool isReady() const { return m_secureReady; } bool isSecureReady(); bool isSecure() { return true; } @@ -79,5 +78,4 @@ private: private: Ssl* m_ssl; bool m_secureReady; - String m_certFingerprintFilename; }; diff --git a/src/lib/synergy/ArgParser.cpp b/src/lib/synergy/ArgParser.cpp index 82186b3a..bec60632 100644 --- a/src/lib/synergy/ArgParser.cpp +++ b/src/lib/synergy/ArgParser.cpp @@ -89,10 +89,6 @@ ArgParser::parseClientArgs(ClientArgs& args, int argc, const char* const* argv) // define scroll args.m_yscroll = atoi(argv[++i]); } - else if (isArg(i, argc, argv, NULL, "--certificate-fingerprint", 1)) { - // define scroll - args.m_certFingerprintFilename = argv[++i]; - } else { if (i + 1 == argc) { args.m_synergyAddress = argv[i]; diff --git a/src/lib/synergy/ClientArgs.cpp b/src/lib/synergy/ClientArgs.cpp index fff34817..c997f3cc 100644 --- a/src/lib/synergy/ClientArgs.cpp +++ b/src/lib/synergy/ClientArgs.cpp @@ -18,7 +18,6 @@ #include "synergy/ClientArgs.h" ClientArgs::ClientArgs() : - m_yscroll(0), - m_certFingerprintFilename() + m_yscroll(0) { } diff --git a/src/lib/synergy/ClientArgs.h b/src/lib/synergy/ClientArgs.h index 093b0ccf..45b73e3c 100644 --- a/src/lib/synergy/ClientArgs.h +++ b/src/lib/synergy/ClientArgs.h @@ -27,5 +27,4 @@ public: public: int m_yscroll; - String m_certFingerprintFilename; }; From c7de2da062406a9d61ef7724d008a64515cbc125 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 15 Apr 2015 14:33:26 +0100 Subject: [PATCH 20/49] Comment out unused fingerprint filename consts #4522 Causing compile to fail on Mac (fails on warnings) --- src/lib/plugin/ns/SecureSocket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 7de15eff..651fd432 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -37,9 +37,9 @@ #define MAX_ERROR_SIZE 65535 static const char kFingerprintDirName[] = "ssl/fingerprints"; -static const char kFingerprintLocalFilename[] = "local.txt"; +//static const char kFingerprintLocalFilename[] = "local.txt"; static const char kFingerprintTrustedServersFilename[] = "trusted-servers.txt"; -static const char kFingerprintTrustedClientsFilename[] = "trusted-clients.txt"; +//static const char kFingerprintTrustedClientsFilename[] = "trusted-clients.txt"; struct Ssl { SSL_CTX* m_context; From 14bf90264ef4e93d3725b5065fee61f7149f1eae Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 15 Apr 2015 14:49:05 +0100 Subject: [PATCH 21/49] Renamed function, was reserved keyword on Mac #4522 --- src/gui/src/Fingerprint.cpp | 2 +- src/gui/src/Fingerprint.h | 2 +- src/gui/src/MainWindow.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index 0ff15a44..70b5c786 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -56,7 +56,7 @@ void Fingerprint::trust(const QString& fingerprintText) } } -bool Fingerprint::check(const QString& fingerprintText) +bool Fingerprint::exists(const QString& fingerprintText) { CoreInterface coreInterface; QString profileDir = coreInterface.getProfileDir(); diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h index d494af0b..8618b521 100644 --- a/src/gui/src/Fingerprint.h +++ b/src/gui/src/Fingerprint.h @@ -26,7 +26,7 @@ private: public: void trust(const QString& fingerprintText); - bool check(const QString& fingerprintText); + bool exists(const QString& fingerprintText); public: static Fingerprint local(); diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index c4e8b0fc..794359f9 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -409,7 +409,7 @@ void MainWindow::checkFingerprint(const QString& line) } QString fingerprint = fingerprintRegex.cap(1); - if (Fingerprint::trustedServers().check(fingerprint)) { + if (Fingerprint::trustedServers().exists(fingerprint)) { return; } From 7c6561b3da88ace29586ea6a622ac7be3dc81a85 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Wed, 15 Apr 2015 15:17:26 +0100 Subject: [PATCH 22/49] Fixed #4528 - invalid/misleading log line --- src/lib/plugin/ns/SecureSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 651fd432..5b1544db 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -379,7 +379,7 @@ SecureSocket::checkResult(int n, bool& fatal, bool& retry) break; default: - LOG((CLOG_ERR "secure socket error: SSL_ERROR_SSL")); + LOG((CLOG_ERR "secure socket error: unknown")); fatal = true; break; } From 7ab1081b3f9f8b4be6fcc224046bbed5723ce127 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Thu, 16 Apr 2015 11:55:05 +0100 Subject: [PATCH 23/49] Fixed server crash caused by double delete a socket #4535 --- src/lib/plugin/ns/SecureListenSocket.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/plugin/ns/SecureListenSocket.cpp b/src/lib/plugin/ns/SecureListenSocket.cpp index 562a6899..86907608 100644 --- a/src/lib/plugin/ns/SecureListenSocket.cpp +++ b/src/lib/plugin/ns/SecureListenSocket.cpp @@ -55,7 +55,6 @@ SecureListenSocket::accept() m_socketMultiplexer, ARCH->acceptSocket(m_socket, NULL)); socket->initSsl(true); - m_secureSocketSet.insert(socket); if (socket != NULL) { setListeningJob(); @@ -78,6 +77,8 @@ SecureListenSocket::accept() socket->secureAccept(); + m_secureSocketSet.insert(socket); + return dynamic_cast(socket); } catch (XArchNetwork&) { From 88538e5ee6ce8a3901503ed50a04992d96868150 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Thu, 16 Apr 2015 15:10:33 +0100 Subject: [PATCH 24/49] Resolve #4526 added local fingerprint in server GUI --- src/gui/res/MainWindowBase.ui | 28 ++++++++++++++++++++-- src/gui/src/Fingerprint.cpp | 29 ++++++++++++++++++++++ src/gui/src/Fingerprint.h | 2 ++ src/gui/src/MainWindow.cpp | 12 ++++++++++ src/gui/src/PluginManager.cpp | 45 +++++++++++++++++++++++++++++++++-- src/gui/src/PluginManager.h | 1 + 6 files changed, 113 insertions(+), 4 deletions(-) diff --git a/src/gui/res/MainWindowBase.ui b/src/gui/res/MainWindowBase.ui index 73917975..0a47e0d3 100644 --- a/src/gui/res/MainWindowBase.ui +++ b/src/gui/res/MainWindowBase.ui @@ -1,4 +1,4 @@ - + MainWindowBase @@ -117,6 +117,30 @@ + + + + + + + 0 + 0 + + + + Fingerprint: + + + + + + + + + + + + @@ -128,7 +152,7 @@ - + diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index 70b5c786..e120ef55 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -102,3 +102,32 @@ Fingerprint Fingerprint::trustedClients() { return Fingerprint(kTrustedClientsFilename); } + +QString Fingerprint::localFingerprint() +{ + CoreInterface coreInterface; + QString profileDir = coreInterface.getProfileDir(); + + QString dirName = QString("%1/%2") + .arg(profileDir) + .arg(kDirName); + + QString path = QString("%1/%2").arg(dirName).arg(kLocalFilename); + + QFile file(path); + QString fingerprint; + if (file.open(QIODevice::ReadOnly)) + { + QTextStream in(&file); + while (!in.atEnd()) + { + QString context = in.readLine(); + if (!context.isEmpty()) { + fingerprint = context; + } + } + file.close(); + } + + return fingerprint; +} diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h index 8618b521..342c51bc 100644 --- a/src/gui/src/Fingerprint.h +++ b/src/gui/src/Fingerprint.h @@ -33,6 +33,8 @@ public: static Fingerprint trustedServers(); static Fingerprint trustedClients(); + static QString localFingerprint(); + private: QString m_Filename; }; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 794359f9..72f38516 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -941,6 +941,17 @@ void MainWindow::setEdition(int type) } setWindowTitle(title); + + if (type == Pro) { + m_pLabelFingerprint->setVisible(true); + m_pLabelLocalFingerprint->setVisible(true); + m_pLabelLocalFingerprint->setText( + Fingerprint::localFingerprint()); + } + else { + m_pLabelFingerprint->setVisible(false); + m_pLabelLocalFingerprint->setVisible(false); + } } void MainWindow::on_m_pGroupClient_toggled(bool on) @@ -1222,6 +1233,7 @@ void MainWindow::updateEdition() QString mac = getFirstMacAddress(); QString hashSrc = m_AppConfig.activateEmail() + mac; QString hashResult = hash(hashSrc); + if (hashResult == m_AppConfig.userToken()) { setEdition(m_AppConfig.edition()); } diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index c3ce8d03..813f52e1 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -39,6 +39,8 @@ static QString kCertificateLifetime = "365"; static QString kCertificateSubjectInfo = "/CN=Synergy"; static QString kCertificateFilename = "Synergy.pem"; static QString kUnixOpenSslCommand = "openssl"; +static const char kFingerprintDir[] = "ssl/fingerprints"; +static const char kFingerprintLocalFilename[] = "local.txt"; #if defined(Q_OS_WIN) static const char kWinPluginExt[] = ".dll"; @@ -353,6 +355,45 @@ void PluginManager::doGenerateCertificate() return; } + // generate fingerprint + arguments.clear(); + arguments.append("x509"); + arguments.append("-fingerprint"); + arguments.append("-sha1"); + arguments.append("-noout"); + arguments.append("-in"); + arguments.append(filename); + + if (!runProgram(openSslProgramFile, arguments, environment)) { + return; + } + + // write the standard output into file + filename.clear(); + filename.append(m_ProfileDir); + filename.append(QDir::separator()).append(kFingerprintDir); + QDir dir(filename); + if (!dir.exists()) { + dir.mkpath("."); + } + filename.append(QDir::separator()).append(kFingerprintLocalFilename); + + // only write the fingerprint part + int i = m_standardOutput.indexOf("="); + if (i != -1) { + i++; + QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); + + QFile file(filename); + file.resize(0); + if (file.open(QIODevice::Append)) + { + QTextStream out(&file); + out << fingerprint << "\n"; + file.close(); + } + } + emit generateCertificateFinished(); } @@ -365,10 +406,10 @@ bool PluginManager::runProgram( bool success = process.waitForStarted(); - QString standardOutput, standardError; + QString standardError; if (success && process.waitForFinished()) { - standardOutput = process.readAllStandardOutput().trimmed(); + m_standardOutput = process.readAllStandardOutput().trimmed(); standardError = process.readAllStandardError().trimmed(); } diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index 31b987a9..c7e52c30 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -67,6 +67,7 @@ private: int m_DownloadIndex; DataDownloader m_DataDownloader; CoreInterface m_CoreInterface; + QString m_standardOutput; }; #endif // PLUGINMANAGER_H From 59d013ac6af0dedd9ea6259580e0143367a343eb Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Thu, 16 Apr 2015 17:12:42 +0100 Subject: [PATCH 25/49] Show fingerprint only when file exists #4526 --- src/gui/src/Fingerprint.cpp | 20 ++++++++++++++++++++ src/gui/src/Fingerprint.h | 1 + src/gui/src/MainWindow.cpp | 23 ++++++++++++----------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index e120ef55..6eefdcd5 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -88,6 +88,26 @@ bool Fingerprint::exists(const QString& fingerprintText) return false; } +bool Fingerprint::localFingerprintExists() +{ + CoreInterface coreInterface; + QString profileDir = coreInterface.getProfileDir(); + + QString dirName = QString("%1/%2") + .arg(profileDir) + .arg(kDirName); + + QString path = QString("%1/%2").arg(dirName).arg(kLocalFilename); + QFile file(path); + + bool exist = false; + if (file.exists()) { + exist = true; + } + + return exist; +} + Fingerprint Fingerprint::local() { return Fingerprint(kLocalFilename); diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h index 342c51bc..179afef9 100644 --- a/src/gui/src/Fingerprint.h +++ b/src/gui/src/Fingerprint.h @@ -34,6 +34,7 @@ public: static Fingerprint trustedClients(); static QString localFingerprint(); + static bool localFingerprintExists(); private: QString m_Filename; diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 72f38516..9da5b94a 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -23,6 +23,7 @@ #include "MainWindow.h" #include "Fingerprint.h" +#include "PluginManager.h" #include "AboutDialog.h" #include "ServerConfigDialog.h" #include "SettingsDialog.h" @@ -133,6 +134,17 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : updateEdition(); m_pLabelPadlock->hide(); + + if (Fingerprint::localFingerprintExists()) { + m_pLabelFingerprint->setVisible(true); + m_pLabelLocalFingerprint->setVisible(true); + m_pLabelLocalFingerprint->setText( + Fingerprint::localFingerprint()); + } + else { + m_pLabelFingerprint->setVisible(false); + m_pLabelLocalFingerprint->setVisible(false); + } } MainWindow::~MainWindow() @@ -941,17 +953,6 @@ void MainWindow::setEdition(int type) } setWindowTitle(title); - - if (type == Pro) { - m_pLabelFingerprint->setVisible(true); - m_pLabelLocalFingerprint->setVisible(true); - m_pLabelLocalFingerprint->setText( - Fingerprint::localFingerprint()); - } - else { - m_pLabelFingerprint->setVisible(false); - m_pLabelLocalFingerprint->setVisible(false); - } } void MainWindow::on_m_pGroupClient_toggled(bool on) From 951cbe9a62089014b1a73e321e011f16f4fee7bd Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Thu, 16 Apr 2015 17:15:58 +0100 Subject: [PATCH 26/49] Enable network security checkbox only when ns plugin exists #4540 --- src/gui/src/PluginManager.cpp | 43 ++++++++++++++++++++++++---------- src/gui/src/PluginManager.h | 5 +++- src/gui/src/SettingsDialog.cpp | 8 +++---- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 813f52e1..38b60833 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -74,6 +74,23 @@ PluginManager::~PluginManager() { } +bool PluginManager::exist(QString name) +{ + CoreInterface coreInterface; + QString PluginDir = coreInterface.getPluginDir(); + QString pluginName = getPluginOsSpecificName(name); + QString filename; + filename.append(PluginDir); + filename.append(QDir::separator()).append(pluginName); + QFile file(filename); + bool exist = false; + if (file.exists()) { + exist = true; + } + + return exist; +} + void PluginManager::downloadPlugins() { if (m_DataDownloader.isFinished()) { @@ -251,19 +268,6 @@ QString PluginManager::getOpenSslSetupUrl() return result; } -QString PluginManager::getPluginOsSpecificName(const QString& pluginName) -{ - QString result = pluginName; -#if defined(Q_OS_WIN) - result.append(kWinPluginExt); -#elif defined(Q_OS_MAC) - result = kMacPluginPrefix + pluginName + kMacPluginExt; -#else - result = kLinuxPluginPrefix + pluginName + kLinuxPluginExt; -#endif - return result; -} - bool PluginManager::checkOpenSslBinary() { // assume OpenSsl is unavailable on Windows, @@ -426,3 +430,16 @@ bool PluginManager::runProgram( return true; } + +QString PluginManager::getPluginOsSpecificName(const QString& pluginName) +{ + QString result = pluginName; +#if defined(Q_OS_WIN) + result.append(kWinPluginExt); +#elif defined(Q_OS_MAC) + result = kMacPluginPrefix + pluginName + kMacPluginExt; +#else + result = kLinuxPluginPrefix + pluginName + kLinuxPluginExt; +#endif + return result; +} diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index c7e52c30..51e58e0a 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -35,6 +35,8 @@ public: int downloadIndex() { return m_DownloadIndex; } + static bool exist(QString name); + public slots: void downloadPlugins(); void saveOpenSslSetup(); @@ -45,7 +47,6 @@ private: void savePlugin(); QString getPluginUrl(const QString& pluginName); QString getOpenSslSetupUrl(); - QString getPluginOsSpecificName(const QString& pluginName); bool checkOpenSslBinary(); void downloadOpenSslSetup(); bool runProgram( @@ -53,6 +54,8 @@ private: const QStringList& args, const QStringList& env); + static QString getPluginOsSpecificName(const QString& pluginName); + signals: void error(QString e); void downloadNext(); diff --git a/src/gui/src/SettingsDialog.cpp b/src/gui/src/SettingsDialog.cpp index 7f6318a5..04e83c79 100644 --- a/src/gui/src/SettingsDialog.cpp +++ b/src/gui/src/SettingsDialog.cpp @@ -18,6 +18,7 @@ #include "SettingsDialog.h" +#include "PluginManager.h" #include "CoreInterface.h" #include "SynergyLocale.h" #include "QSynergyApplication.h" @@ -30,6 +31,8 @@ #include #include +static const char networkSecurity[] = "ns"; + SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), Ui::SettingsDialogBase(), @@ -57,10 +60,7 @@ SettingsDialog::SettingsDialog(QWidget* parent, AppConfig& config) : m_pCheckBoxElevateMode->hide(); #endif - QString pluginDir = m_CoreInterface.getPluginDir(); - QDir dir(pluginDir); - int fileNum = dir.entryInfoList(QDir::NoDotAndDotDot|QDir::AllEntries).count(); - if (fileNum == 0) { + if (!PluginManager::exist(networkSecurity)) { m_pGroupNetworkSecurity->setEnabled(false); m_pCheckBoxEnableCrypto->setChecked(false); } From 586a8932014d08d72ddc4692007a39196ec870b5 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Fri, 17 Apr 2015 14:01:35 +0100 Subject: [PATCH 27/49] Made retry secure write/read use the exactly last parameters #4539 --- src/lib/net/TCPSocket.cpp | 14 +++++++++++++- src/lib/plugin/ns/SecureSocket.cpp | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/lib/net/TCPSocket.cpp b/src/lib/net/TCPSocket.cpp index c54df40b..62175664 100644 --- a/src/lib/net/TCPSocket.cpp +++ b/src/lib/net/TCPSocket.cpp @@ -461,15 +461,26 @@ TCPSocket::serviceConnected(ISocketMultiplexerJob* job, } bool needNewJob = false; + static UInt32 s_retryOutputBufferSize = 0; if (write) { try { // write data UInt32 n = m_outputBuffer.getSize(); + + if (s_retryOutputBufferSize > 0) { + n = s_retryOutputBufferSize; + } + const void* buffer = m_outputBuffer.peek(n); if (isSecure()) { if (isSecureReady()) { + s_retryOutputBufferSize = n; n = secureWrite(buffer, n); + + if (n > 0) { + s_retryOutputBufferSize = 0; + } } else { return job; @@ -519,7 +530,8 @@ TCPSocket::serviceConnected(ISocketMultiplexerJob* job, if (read && m_readable) { try { - UInt8 buffer[4096]; + static UInt8 buffer[4096]; + memset(buffer, 0, sizeof(buffer)); size_t n = 0; if (isSecure()) { diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 5b1544db..c878871d 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -370,6 +370,21 @@ SecureSocket::checkResult(int n, bool& fatal, bool& retry) case SSL_ERROR_SYSCALL: LOG((CLOG_ERR "secure socket error: SSL_ERROR_SYSCALL")); + if (ERR_peek_error() == 0) { + if (n == 0) { + LOG((CLOG_ERR "an EOF violates the protocol")); + } + else if (n == -1) { + // underlying socket I/O reproted an error + try { + ARCH->throwErrorOnSocket(getSocket()); + } + catch (XArchNetwork& e) { + LOG((CLOG_ERR "%s", e.what())); + } + } + } + fatal = true; break; From 365d16c94b1b9a605666eb6623d95b3251765d86 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Fri, 17 Apr 2015 16:33:43 +0100 Subject: [PATCH 28/49] Added more status details #4537 --- src/gui/src/PluginManager.cpp | 10 ++++++++-- src/gui/src/PluginManager.h | 1 + src/gui/src/PluginWizardPage.cpp | 5 +++++ src/gui/src/PluginWizardPage.h | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 38b60833..453fd869 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -156,6 +156,7 @@ void PluginManager::saveOpenSslSetup() // openssl installer no longer needed QFile::remove(filename); + emit info(tr("SSL tools ready")); #endif emit openSslBinaryReady(); @@ -304,6 +305,8 @@ void PluginManager::downloadOpenSslSetup() SLOT(saveOpenSslSetup())); m_DataDownloader.download(url); + + emit info(tr("Downloading SSL tools...")); } void PluginManager::doGenerateCertificate() @@ -331,8 +334,8 @@ void PluginManager::doGenerateCertificate() // subject information arguments.append("-subj"); - QString info(kCertificateSubjectInfo); - arguments.append(info); + QString subInfo(kCertificateSubjectInfo); + arguments.append(subInfo); // private key arguments.append("-newkey"); @@ -359,6 +362,8 @@ void PluginManager::doGenerateCertificate() return; } + emit info(tr("SSL certificate generated")); + // generate fingerprint arguments.clear(); arguments.append("x509"); @@ -395,6 +400,7 @@ void PluginManager::doGenerateCertificate() QTextStream out(&file); out << fingerprint << "\n"; file.close(); + emit info(tr("SSL fingerprint generated")); } } diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index 51e58e0a..54cab017 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -58,6 +58,7 @@ private: signals: void error(QString e); + void info(QString i); void downloadNext(); void downloadFinished(); void openSslBinaryReady(); diff --git a/src/gui/src/PluginWizardPage.cpp b/src/gui/src/PluginWizardPage.cpp index 0cc5d782..8c0a4d05 100644 --- a/src/gui/src/PluginWizardPage.cpp +++ b/src/gui/src/PluginWizardPage.cpp @@ -135,6 +135,11 @@ void PluginWizardPage::downloadPlugins() this, SLOT(showError(QString))); + connect(m_pPluginManager, + SIGNAL(info(QString)), + this, + SLOT(updateStatus(QString))); + connect(m_pPluginManager, SIGNAL(downloadNext()), this, diff --git a/src/gui/src/PluginWizardPage.h b/src/gui/src/PluginWizardPage.h index ed224201..0300ebac 100644 --- a/src/gui/src/PluginWizardPage.h +++ b/src/gui/src/PluginWizardPage.h @@ -46,13 +46,13 @@ protected: protected slots: void showError(QString error); + void updateStatus(QString info); void queryPluginDone(); void updateDownloadStatus(); void finished(); void generateCertificate(); private: - void updateStatus(QString info); void downloadPlugins(); void showFinished(); From 05b833d1b66f2e6068175f539dc3d716dbc67e38 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 14:35:29 +0100 Subject: [PATCH 29/49] Added OpenSSL config file #4546 --- res/openssl/synergy.conf | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 res/openssl/synergy.conf diff --git a/res/openssl/synergy.conf b/res/openssl/synergy.conf new file mode 100644 index 00000000..c7a3e439 --- /dev/null +++ b/res/openssl/synergy.conf @@ -0,0 +1,65 @@ +# +# Synergy OpenSSL configuration file. +# Used for generation of certificate requests. +# + +dir = . + +[ca] +default_ca = CA_default + +[CA_default] +serial = $dir/serial +database = $dir/certindex.txt +new_certs_dir = $dir/certs +certificate = $dir/cacert.pem +private_key = $dir/private/cakey.pem +default_days = 365 +default_md = md5 +preserve = no +email_in_dn = no +nameopt = default_ca +certopt = default_ca +policy = policy_match + +[policy_match] +countryName = match +stateOrProvinceName = match +organizationName = match +organizationalUnitName = optional +commonName = supplied +emailAddress = optional + +[req] +default_bits = 1024 # Size of keys +default_keyfile = key.pem # name of generated keys +default_md = md5 # message digest algorithm +string_mask = nombstr # permitted characters +distinguished_name = req_distinguished_name +req_extensions = v3_req + +[req_distinguished_name] +0.organizationName = Organization Name (company) +organizationalUnitName = Organizational Unit Name (department, division) +emailAddress = Email Address +emailAddress_max = 40 +localityName = Locality Name (city, district) +stateOrProvinceName = State or Province Name (full name) +countryName = Country Name (2 letter code) +countryName_min = 2 +countryName_max = 2 +commonName = Common Name (hostname, IP, or your name) +commonName_max = 64 +0.organizationName_default = My Company +localityName_default = My Town +stateOrProvinceName_default = State or Providence +countryName_default = US + +[v3_ca] +basicConstraints = CA:TRUE +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always + +[v3_req] +basicConstraints = CA:FALSE +subjectKeyIdentifier = hash From 453638fa397ce244934fdc7c06fbcf0900984538 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 14:35:52 +0100 Subject: [PATCH 30/49] Added OpenSSL component to installer #4546 --- src/setup/win32/Product.wxs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/setup/win32/Product.wxs b/src/setup/win32/Product.wxs index df61f862..884e329b 100644 --- a/src/setup/win32/Product.wxs +++ b/src/setup/win32/Product.wxs @@ -26,6 +26,7 @@ + @@ -61,6 +62,7 @@ + @@ -68,6 +70,7 @@ + @@ -112,5 +115,14 @@ + + + + + + + + + From e6e3eae0a9a101b977622dab9cfdf3cc8aaa5ce8 Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Mon, 20 Apr 2015 14:43:39 +0100 Subject: [PATCH 31/49] Disabled reconnect after fingerprint failed #4527 --- src/lib/base/EventTypes.cpp | 1 + src/lib/base/EventTypes.h | 11 ++++++++++- src/lib/client/Client.cpp | 13 ++++++++++++- src/lib/client/Client.h | 5 +++-- src/lib/plugin/ns/SecureSocket.cpp | 3 +-- src/lib/synergy/ClientApp.cpp | 1 - 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/lib/base/EventTypes.cpp b/src/lib/base/EventTypes.cpp index 5ef90e8d..d317e1d7 100644 --- a/src/lib/base/EventTypes.cpp +++ b/src/lib/base/EventTypes.cpp @@ -95,6 +95,7 @@ REGISTER_EVENT(IListenSocket, connecting) // REGISTER_EVENT(ISocket, disconnected) +REGISTER_EVENT(ISocket, stopRetry) // // OSXScreen diff --git a/src/lib/base/EventTypes.h b/src/lib/base/EventTypes.h index dc605f21..74bbed63 100644 --- a/src/lib/base/EventTypes.h +++ b/src/lib/base/EventTypes.h @@ -281,7 +281,8 @@ private: class ISocketEvents : public EventTypes { public: ISocketEvents() : - m_disconnected(Event::kUnknown) { } + m_disconnected(Event::kUnknown), + m_stopRetry(Event::kUnknown) { } //! @name accessors //@{ @@ -294,10 +295,18 @@ public: */ Event::Type disconnected(); + //! Get stop retry event type + /*! + Returns the stop retry event type. This is sent when the client + doesn't want to reconnect after it disconnects from the server. + */ + Event::Type stopRetry(); + //@} private: Event::Type m_disconnected; + Event::Type m_stopRetry; }; class OSXScreenEvents : public EventTypes { diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index 9c7d785d..3e59c942 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -60,7 +60,7 @@ Client::Client( const String& name, const NetworkAddress& address, ISocketFactory* socketFactory, synergy::Screen* screen, - ClientArgs args) : + ClientArgs& args) : m_mock(false), m_name(name), m_serverAddress(address), @@ -470,6 +470,10 @@ Client::setupConnection() m_stream->getEventTarget(), new TMethodEventJob(this, &Client::handleDisconnected)); + + m_events->adoptHandler(m_events->forISocket().stopRetry(), + m_stream->getEventTarget(), + new TMethodEventJob(this, &Client::handleStopRetry)); } void @@ -525,6 +529,8 @@ Client::cleanupConnection() m_stream->getEventTarget()); m_events->removeHandler(m_events->forISocket().disconnected(), m_stream->getEventTarget()); + m_events->removeHandler(m_events->forISocket().stopRetry(), + m_stream->getEventTarget()); cleanupStream(); } } @@ -743,6 +749,11 @@ Client::onFileRecieveCompleted() } } +void +Client::handleStopRetry(const Event&, void*) +{ + m_args.m_restartable = false; +} void Client::writeToDropDirThread(void*) diff --git a/src/lib/client/Client.h b/src/lib/client/Client.h index e50b567b..c3bdfaba 100644 --- a/src/lib/client/Client.h +++ b/src/lib/client/Client.h @@ -60,7 +60,7 @@ public: const String& name, const NetworkAddress& address, ISocketFactory* socketFactory, synergy::Screen* screen, - ClientArgs args); + ClientArgs& args); ~Client(); #ifdef TEST_ENV @@ -196,6 +196,7 @@ private: void handleResume(const Event& event, void*); void handleFileChunkSending(const Event&, void*); void handleFileRecieveCompleted(const Event&, void*); + void handleStopRetry(const Event&, void*); void onFileRecieveCompleted(); public: @@ -226,5 +227,5 @@ private: Thread* m_writeToDropDirThread; TCPSocket* m_socket; bool m_useSecureNetwork; - ClientArgs m_args; + ClientArgs& m_args; }; diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index c878871d..ccc3ec01 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -281,10 +281,8 @@ SecureSocket::secureConnect(int socket) checkResult(r, fatal, retry); if (fatal) { - // tell user and sleep so the socket isn't hammered. LOG((CLOG_ERR "failed to connect secure socket")); LOG((CLOG_INFO "server connection may not be secure")); - disconnect(); return false; } @@ -299,6 +297,7 @@ SecureSocket::secureConnect(int socket) } else { LOG((CLOG_ERR "failed to verify server certificate fingerprint")); + sendEvent(getEvents()->forISocket().stopRetry()); disconnect(); } } diff --git a/src/lib/synergy/ClientApp.cpp b/src/lib/synergy/ClientApp.cpp index f27a8331..dd262a93 100644 --- a/src/lib/synergy/ClientApp.cpp +++ b/src/lib/synergy/ClientApp.cpp @@ -331,7 +331,6 @@ ClientApp::handleClientDisconnected(const Event&, void*) updateStatus(); } - Client* ClientApp::openClient(const String& name, const NetworkAddress& address, synergy::Screen* screen) From cf6a6bcd48f6f95c36e016e906cfceded7269f56 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Mon, 20 Apr 2015 14:57:59 +0100 Subject: [PATCH 32/49] Removed dead code #4527 --- src/lib/client/Client.h | 4 ---- src/test/mock/client/MockClient.h | 37 ------------------------------- 2 files changed, 41 deletions(-) delete mode 100644 src/test/mock/client/MockClient.h diff --git a/src/lib/client/Client.h b/src/lib/client/Client.h index c3bdfaba..9245a825 100644 --- a/src/lib/client/Client.h +++ b/src/lib/client/Client.h @@ -62,10 +62,6 @@ public: synergy::Screen* screen, ClientArgs& args); ~Client(); - -#ifdef TEST_ENV - Client() : m_mock(true) { } -#endif //! @name manipulators //@{ diff --git a/src/test/mock/client/MockClient.h b/src/test/mock/client/MockClient.h deleted file mode 100644 index 427c9fe6..00000000 --- a/src/test/mock/client/MockClient.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * synergy -- mouse and keyboard sharing utility - * Copyright (C) 2012 Synergy Si Ltd. - * Copyright (C) 2011 Nick Bolton - * - * This package is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * found in the file COPYING that should have accompanied this file. - * - * This package is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#define TEST_ENV - -#include "client/Client.h" - -#include "test/global/gmock.h" - -class IEventQueue; - -class MockClient : public Client -{ -public: - MockClient() : Client() { } - MOCK_METHOD2(mouseMove, void(SInt32, SInt32)); - MOCK_METHOD1(setOptions, void(const OptionsList&)); - MOCK_METHOD0(handshakeComplete, void()); - MOCK_METHOD1(setDecryptIv, void(const UInt8*)); -}; From 36a6bb921826a5a876d30e74dfd5fe27bec53748 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 15:27:24 +0100 Subject: [PATCH 33/49] Removed OpenSSL download from plugin manager #4546 --- src/gui/src/PluginManager.cpp | 227 ++++++++++++++-------------------- src/gui/src/PluginManager.h | 1 - 2 files changed, 94 insertions(+), 134 deletions(-) diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 453fd869..3c548a15 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -26,6 +26,7 @@ #include #include #include +#include static QString kBaseUrl = "http://synergy-project.org/files"; static const char kWinProcessorArch32[] = "Windows-x86"; @@ -164,13 +165,100 @@ void PluginManager::saveOpenSslSetup() void PluginManager::generateCertificate() { - connect( - this, - SIGNAL(openSslBinaryReady()), - this, - SLOT(doGenerateCertificate())); + QString openSslProgramFile; - downloadOpenSslSetup(); +#if defined(Q_OS_WIN) + openSslProgramFile = QCoreApplication::applicationDirPath(); + openSslProgramFile.append("\\").append(kWinOpenSslBinary); +#else + openSslProgramFile = kUnixOpenSslCommand; +#endif + + QStringList arguments; + + // self signed certificate + arguments.append("req"); + arguments.append("-x509"); + arguments.append("-nodes"); + + // valide duration + arguments.append("-days"); + arguments.append(kCertificateLifetime); + + // subject information + arguments.append("-subj"); + + QString subInfo(kCertificateSubjectInfo); + arguments.append(subInfo); + + // private key + arguments.append("-newkey"); + arguments.append("rsa:1024"); + + // key output filename + arguments.append("-keyout"); + QString filename = m_ProfileDir; + filename.append(QDir::separator()).append(kCertificateFilename); + arguments.append(filename); + + // certificate output filename + arguments.append("-out"); + arguments.append(filename); + + QStringList environment; + +#if defined(Q_OS_WIN) + environment << QString("OPENSSL_CONF=%1\\OpenSSL\\synergy.conf") + .arg(QCoreApplication::applicationDirPath()); +#endif + + if (!runProgram(openSslProgramFile, arguments, environment)) { + return; + } + + emit info(tr("SSL certificate generated")); + + // generate fingerprint + arguments.clear(); + arguments.append("x509"); + arguments.append("-fingerprint"); + arguments.append("-sha1"); + arguments.append("-noout"); + arguments.append("-in"); + arguments.append(filename); + + if (!runProgram(openSslProgramFile, arguments, environment)) { + return; + } + + // write the standard output into file + filename.clear(); + filename.append(m_ProfileDir); + filename.append(QDir::separator()).append(kFingerprintDir); + QDir dir(filename); + if (!dir.exists()) { + dir.mkpath("."); + } + filename.append(QDir::separator()).append(kFingerprintLocalFilename); + + // only write the fingerprint part + int i = m_standardOutput.indexOf("="); + if (i != -1) { + i++; + QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); + + QFile file(filename); + file.resize(0); + if (file.open(QIODevice::Append)) + { + QTextStream out(&file); + out << fingerprint << "\n"; + file.close(); + emit info(tr("SSL fingerprint generated")); + } + } + + emit generateCertificateFinished(); } void PluginManager::savePlugin() @@ -280,133 +368,6 @@ bool PluginManager::checkOpenSslBinary() #endif } -void PluginManager::downloadOpenSslSetup() -{ - if (checkOpenSslBinary()) { - emit openSslBinaryReady(); - return; - } - - QString urlString = getOpenSslSetupUrl(); - - QUrl url; - url.setUrl(urlString); - - disconnect( - &m_DataDownloader, - SIGNAL(isComplete()), - this, - SLOT(downloadPlugins())); - - connect( - &m_DataDownloader, - SIGNAL(isComplete()), - this, - SLOT(saveOpenSslSetup())); - - m_DataDownloader.download(url); - - emit info(tr("Downloading SSL tools...")); -} - -void PluginManager::doGenerateCertificate() -{ - QString openSslProgramFile; - -#if defined(Q_OS_WIN) - openSslProgramFile = m_ProfileDir; - openSslProgramFile.append("\\").append(kWinOpenSslBinary); -#else - openSslProgramFile = kUnixOpenSslCommand; -#endif - - QStringList arguments; - - // self signed certificate - arguments.append("req"); - arguments.append("-x509"); - arguments.append("-nodes"); - - // valide duration - arguments.append("-days"); - arguments.append(kCertificateLifetime); - - // subject information - arguments.append("-subj"); - - QString subInfo(kCertificateSubjectInfo); - arguments.append(subInfo); - - // private key - arguments.append("-newkey"); - arguments.append("rsa:1024"); - - // key output filename - arguments.append("-keyout"); - QString filename = m_ProfileDir; - filename.append(QDir::separator()).append(kCertificateFilename); - arguments.append(filename); - - // certificate output filename - arguments.append("-out"); - arguments.append(filename); - - QStringList environment; - -#if defined(Q_OS_WIN) - environment << QString("OPENSSL_CONF=%1\\OpenSSL\\synergy.conf") - .arg(m_ProfileDir); -#endif - - if (!runProgram(openSslProgramFile, arguments, environment)) { - return; - } - - emit info(tr("SSL certificate generated")); - - // generate fingerprint - arguments.clear(); - arguments.append("x509"); - arguments.append("-fingerprint"); - arguments.append("-sha1"); - arguments.append("-noout"); - arguments.append("-in"); - arguments.append(filename); - - if (!runProgram(openSslProgramFile, arguments, environment)) { - return; - } - - // write the standard output into file - filename.clear(); - filename.append(m_ProfileDir); - filename.append(QDir::separator()).append(kFingerprintDir); - QDir dir(filename); - if (!dir.exists()) { - dir.mkpath("."); - } - filename.append(QDir::separator()).append(kFingerprintLocalFilename); - - // only write the fingerprint part - int i = m_standardOutput.indexOf("="); - if (i != -1) { - i++; - QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); - - QFile file(filename); - file.resize(0); - if (file.open(QIODevice::Append)) - { - QTextStream out(&file); - out << fingerprint << "\n"; - file.close(); - emit info(tr("SSL fingerprint generated")); - } - } - - emit generateCertificateFinished(); -} - bool PluginManager::runProgram( const QString& program, const QStringList& args, const QStringList& env) { diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index 54cab017..9685d1f7 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -41,7 +41,6 @@ public slots: void downloadPlugins(); void saveOpenSslSetup(); void generateCertificate(); - void doGenerateCertificate(); private: void savePlugin(); From 80fd3cc01b3aa83dfb4c7edaf5a33d9b8a2bdc8e Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 15:58:11 +0100 Subject: [PATCH 34/49] Refactored fingerprint file path logic #4525 --- src/gui/src/Fingerprint.cpp | 50 ++++++++++++++++++++--------------- src/gui/src/Fingerprint.h | 4 ++- src/gui/src/PluginManager.cpp | 11 ++------ 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index 6eefdcd5..502a4a06 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -34,20 +34,9 @@ Fingerprint::Fingerprint(const QString& filename) void Fingerprint::trust(const QString& fingerprintText) { - CoreInterface coreInterface; - QString profileDir = coreInterface.getProfileDir(); + Fingerprint::persistDirectory(); - QString dirName = QString("%1/%2") - .arg(profileDir) - .arg(kDirName); - - QDir dir(dirName); - if (!dir.exists()) { - dir.mkpath("."); - } - - QString path = QString("%1/%2").arg(dirName).arg(m_Filename); - QFile file(path); + QFile file(filePath()); if (file.open(QIODevice::Append)) { QTextStream out(&file); @@ -58,19 +47,12 @@ void Fingerprint::trust(const QString& fingerprintText) bool Fingerprint::exists(const QString& fingerprintText) { - CoreInterface coreInterface; - QString profileDir = coreInterface.getProfileDir(); - - QString dirName = QString("%1/%2") - .arg(profileDir) - .arg(kDirName); - + QString dirName = Fingerprint::directoryPath(); if (!QDir(dirName).exists()) { return false; } - QString path = QString("%1/%2").arg(dirName).arg(m_Filename); - QFile file(path); + QFile file(filePath()); if (file.open(QIODevice::ReadOnly)) { @@ -88,6 +70,30 @@ bool Fingerprint::exists(const QString& fingerprintText) return false; } +QString Fingerprint::filePath() const +{ + QString dir = Fingerprint::directoryPath(); + return QString("%1/%2").arg(dir).arg(m_Filename); +} + +void Fingerprint::persistDirectory() +{ + QDir dir(Fingerprint::directoryPath()); + if (!dir.exists()) { + dir.mkpath("."); + } +} + +QString Fingerprint::directoryPath() +{ + CoreInterface coreInterface; + QString profileDir = coreInterface.getProfileDir(); + + return QString("%1/%2") + .arg(profileDir) + .arg(kDirName); +} + bool Fingerprint::localFingerprintExists() { CoreInterface coreInterface; diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h index 179afef9..0da2a7fc 100644 --- a/src/gui/src/Fingerprint.h +++ b/src/gui/src/Fingerprint.h @@ -27,14 +27,16 @@ private: public: void trust(const QString& fingerprintText); bool exists(const QString& fingerprintText); + QString filePath() const; public: static Fingerprint local(); static Fingerprint trustedServers(); static Fingerprint trustedClients(); - + static QString directoryPath(); static QString localFingerprint(); static bool localFingerprintExists(); + static void persistDirectory(); private: QString m_Filename; diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 3c548a15..d62432be 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -22,6 +22,7 @@ #include "DataDownloader.h" #include "QUtility.h" #include "ProcessorArch.h" +#include "Fingerprint.h" #include #include @@ -40,8 +41,6 @@ static QString kCertificateLifetime = "365"; static QString kCertificateSubjectInfo = "/CN=Synergy"; static QString kCertificateFilename = "Synergy.pem"; static QString kUnixOpenSslCommand = "openssl"; -static const char kFingerprintDir[] = "ssl/fingerprints"; -static const char kFingerprintLocalFilename[] = "local.txt"; #if defined(Q_OS_WIN) static const char kWinPluginExt[] = ".dll"; @@ -233,13 +232,7 @@ void PluginManager::generateCertificate() // write the standard output into file filename.clear(); - filename.append(m_ProfileDir); - filename.append(QDir::separator()).append(kFingerprintDir); - QDir dir(filename); - if (!dir.exists()) { - dir.mkpath("."); - } - filename.append(QDir::separator()).append(kFingerprintLocalFilename); + filename.append(Fingerprint::local().filePath()); // only write the fingerprint part int i = m_standardOutput.indexOf("="); From 5e2b8a50483daec83d1552cb7e0ce394113022b4 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Mon, 20 Apr 2015 16:16:53 +0100 Subject: [PATCH 35/49] Fixed #4537 by add file error checking --- src/gui/src/PluginManager.cpp | 17 ++++++++++++----- src/gui/src/PluginManager.h | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 453fd869..863ce9c0 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -94,7 +94,10 @@ bool PluginManager::exist(QString name) void PluginManager::downloadPlugins() { if (m_DataDownloader.isFinished()) { - savePlugin(); + if (!savePlugin()) { + return; + } + if (m_DownloadIndex != m_PluginList.size() - 1) { emit downloadNext(); } @@ -173,7 +176,7 @@ void PluginManager::generateCertificate() downloadOpenSslSetup(); } -void PluginManager::savePlugin() +bool PluginManager::savePlugin() { // create the path if not exist QDir dir(m_PluginDir); @@ -189,15 +192,19 @@ void PluginManager::savePlugin() QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { emit error( - tr("Failed to download '%1' plugin to: %2") + tr("Failed to download plugin '%1' to: %2 \n %3") .arg(m_PluginList.at(m_DownloadIndex)) - .arg(m_PluginDir)); + .arg(m_PluginDir) + .arg(file.errorString())); - return; + file.close(); + return false; } file.write(m_DataDownloader.data()); file.close(); + + return true; } QString PluginManager::getPluginUrl(const QString& pluginName) diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index 54cab017..e6e390e1 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -44,7 +44,7 @@ public slots: void doGenerateCertificate(); private: - void savePlugin(); + bool savePlugin(); QString getPluginUrl(const QString& pluginName); QString getOpenSslSetupUrl(); bool checkOpenSslBinary(); From a649a0e3dfc70d9d0479e8b8e1506ade57ab302a Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 16:28:26 +0100 Subject: [PATCH 36/49] Reduced code duplication in fingerprint logic #4548 --- src/gui/src/Fingerprint.cpp | 102 +++++++++++++++------------------- src/gui/src/Fingerprint.h | 7 ++- src/gui/src/MainWindow.cpp | 7 +-- src/gui/src/PluginManager.cpp | 13 +---- 4 files changed, 57 insertions(+), 72 deletions(-) diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index 502a4a06..6412dcea 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -32,12 +32,20 @@ Fingerprint::Fingerprint(const QString& filename) m_Filename = filename; } -void Fingerprint::trust(const QString& fingerprintText) +void Fingerprint::trust(const QString& fingerprintText, bool append) { Fingerprint::persistDirectory(); + QIODevice::OpenMode openMode; + if (append) { + openMode = QIODevice::Append; + } + else { + openMode = QIODevice::WriteOnly; + } + QFile file(filePath()); - if (file.open(QIODevice::Append)) + if (file.open(openMode)) { QTextStream out(&file); out << fingerprintText << "\n"; @@ -45,13 +53,38 @@ void Fingerprint::trust(const QString& fingerprintText) } } -bool Fingerprint::exists(const QString& fingerprintText) +bool Fingerprint::fileExists() const { QString dirName = Fingerprint::directoryPath(); if (!QDir(dirName).exists()) { return false; } + QFile file(filePath()); + return file.exists(); +} + +bool Fingerprint::isTrusted(const QString& fingerprintText) +{ + QStringList list = readList(); + foreach (QString trusted, list) + { + if (trusted == fingerprintText) { + return true; + } + } + return false; +} + +QStringList Fingerprint::readList(const int readTo) +{ + QStringList list; + + QString dirName = Fingerprint::directoryPath(); + if (!QDir(dirName).exists()) { + return list; + } + QFile file(filePath()); if (file.open(QIODevice::ReadOnly)) @@ -59,15 +92,21 @@ bool Fingerprint::exists(const QString& fingerprintText) QTextStream in(&file); while (!in.atEnd()) { - QString trusted = in.readLine(); - if (fingerprintText == trusted) { - return true; + list.append(in.readLine()); + if (list.size() == readTo) { + break; } } file.close(); } - return false; + return list; +} + +QString Fingerprint::readFirst() +{ + QStringList list = readList(1); + return list.at(0); } QString Fingerprint::filePath() const @@ -94,26 +133,6 @@ QString Fingerprint::directoryPath() .arg(kDirName); } -bool Fingerprint::localFingerprintExists() -{ - CoreInterface coreInterface; - QString profileDir = coreInterface.getProfileDir(); - - QString dirName = QString("%1/%2") - .arg(profileDir) - .arg(kDirName); - - QString path = QString("%1/%2").arg(dirName).arg(kLocalFilename); - QFile file(path); - - bool exist = false; - if (file.exists()) { - exist = true; - } - - return exist; -} - Fingerprint Fingerprint::local() { return Fingerprint(kLocalFilename); @@ -128,32 +147,3 @@ Fingerprint Fingerprint::trustedClients() { return Fingerprint(kTrustedClientsFilename); } - -QString Fingerprint::localFingerprint() -{ - CoreInterface coreInterface; - QString profileDir = coreInterface.getProfileDir(); - - QString dirName = QString("%1/%2") - .arg(profileDir) - .arg(kDirName); - - QString path = QString("%1/%2").arg(dirName).arg(kLocalFilename); - - QFile file(path); - QString fingerprint; - if (file.open(QIODevice::ReadOnly)) - { - QTextStream in(&file); - while (!in.atEnd()) - { - QString context = in.readLine(); - if (!context.isEmpty()) { - fingerprint = context; - } - } - file.close(); - } - - return fingerprint; -} diff --git a/src/gui/src/Fingerprint.h b/src/gui/src/Fingerprint.h index 0da2a7fc..29ef5f7e 100644 --- a/src/gui/src/Fingerprint.h +++ b/src/gui/src/Fingerprint.h @@ -25,9 +25,12 @@ private: Fingerprint(const QString& filename); public: - void trust(const QString& fingerprintText); - bool exists(const QString& fingerprintText); + void trust(const QString& fingerprintText, bool append = true); + bool isTrusted(const QString& fingerprintText); + QStringList readList(const int readTo = -1); + QString readFirst(); QString filePath() const; + bool fileExists() const; public: static Fingerprint local(); diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 9da5b94a..6ca2d549 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -135,11 +135,10 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pLabelPadlock->hide(); - if (Fingerprint::localFingerprintExists()) { + if (Fingerprint::local().fileExists()) { m_pLabelFingerprint->setVisible(true); m_pLabelLocalFingerprint->setVisible(true); - m_pLabelLocalFingerprint->setText( - Fingerprint::localFingerprint()); + m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst()); } else { m_pLabelFingerprint->setVisible(false); @@ -421,7 +420,7 @@ void MainWindow::checkFingerprint(const QString& line) } QString fingerprint = fingerprintRegex.cap(1); - if (Fingerprint::trustedServers().exists(fingerprint)) { + if (Fingerprint::trustedServers().isTrusted(fingerprint)) { return; } diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index d62432be..3587ecf2 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -239,16 +239,9 @@ void PluginManager::generateCertificate() if (i != -1) { i++; QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); - - QFile file(filename); - file.resize(0); - if (file.open(QIODevice::Append)) - { - QTextStream out(&file); - out << fingerprint << "\n"; - file.close(); - emit info(tr("SSL fingerprint generated")); - } + + Fingerprint::local().trust(fingerprint, false); + emit info(tr("SSL fingerprint generated")); } emit generateCertificateFinished(); From 97060d9698977da6aed956083265d54e02de3178 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 16:31:36 +0100 Subject: [PATCH 37/49] Removed unused SSL download code #4546 --- src/gui/src/PluginManager.cpp | 56 ----------------------------------- src/gui/src/PluginManager.h | 3 -- 2 files changed, 59 deletions(-) diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 3587ecf2..8781fe7c 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -44,7 +44,6 @@ static QString kUnixOpenSslCommand = "openssl"; #if defined(Q_OS_WIN) static const char kWinPluginExt[] = ".dll"; -static const char kWinOpenSslSetup[] = "openssl-1.0.2-Windows-x86.exe"; static const char kWinOpenSslBinary[] = "OpenSSL\\openssl.exe"; #elif defined(Q_OS_MAC) @@ -120,48 +119,6 @@ void PluginManager::downloadPlugins() } } -void PluginManager::saveOpenSslSetup() -{ - QDir dir(m_ProfileDir); - if (!dir.exists()) { - dir.mkpath("."); - } - -#if defined(Q_OS_WIN) - - QString filename = - QString("%1\\%2") - .arg(m_ProfileDir) - .arg(kWinOpenSslSetup); - - QFile file(filename); - if (!file.open(QIODevice::WriteOnly)) { - emit error( - tr("Failed to save certificate tool to: %1") - .arg(m_ProfileDir)); - return; - } - - file.write(m_DataDownloader.data()); - file.close(); - - QStringList installArgs; - installArgs.append("-s"); - installArgs.append("-y"); - - if (!runProgram(filename, installArgs, QStringList())) { - return; - } - - // openssl installer no longer needed - QFile::remove(filename); - - emit info(tr("SSL tools ready")); -#endif - - emit openSslBinaryReady(); -} - void PluginManager::generateCertificate() { QString openSslProgramFile; @@ -330,19 +287,6 @@ QString PluginManager::getPluginUrl(const QString& pluginName) return result; } -QString PluginManager::getOpenSslSetupUrl() -{ - QString result; - -#if defined(Q_OS_WIN) - result = kBaseUrl; - result.append("/tools/"); - result.append(kWinOpenSslSetup); -#endif - - return result; -} - bool PluginManager::checkOpenSslBinary() { // assume OpenSsl is unavailable on Windows, diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index 9685d1f7..b9bdfea4 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -39,15 +39,12 @@ public: public slots: void downloadPlugins(); - void saveOpenSslSetup(); void generateCertificate(); private: void savePlugin(); QString getPluginUrl(const QString& pluginName); - QString getOpenSslSetupUrl(); bool checkOpenSslBinary(); - void downloadOpenSslSetup(); bool runProgram( const QString& program, const QStringList& args, From aa9504f43edbf955b673c6e95f6be16f750052f3 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 16:40:50 +0100 Subject: [PATCH 38/49] Changed filenames in app data directory #4525 - Changed `ssl` to `SSL` - Moved pem file to `SSL` --- src/gui/src/Fingerprint.cpp | 8 ++++---- src/gui/src/PluginManager.cpp | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/gui/src/Fingerprint.cpp b/src/gui/src/Fingerprint.cpp index 6412dcea..b2816684 100644 --- a/src/gui/src/Fingerprint.cpp +++ b/src/gui/src/Fingerprint.cpp @@ -22,10 +22,10 @@ #include #include -static const char kDirName[] = "ssl/fingerprints"; -static const char kLocalFilename[] = "local.txt"; -static const char kTrustedServersFilename[] = "trusted-servers.txt"; -static const char kTrustedClientsFilename[] = "trusted-clients.txt"; +static const char kDirName[] = "SSL/Fingerprints"; +static const char kLocalFilename[] = "Local.txt"; +static const char kTrustedServersFilename[] = "TrustedServers.txt"; +static const char kTrustedClientsFilename[] = "TrustedClients.txt"; Fingerprint::Fingerprint(const QString& filename) { diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 8781fe7c..f3883be7 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -40,6 +40,7 @@ static const char kLinuxProcessorArchRpm64[] = "Linux-x86_64-rpm"; static QString kCertificateLifetime = "365"; static QString kCertificateSubjectInfo = "/CN=Synergy"; static QString kCertificateFilename = "Synergy.pem"; +static QString kSslDir = "SSL"; static QString kUnixOpenSslCommand = "openssl"; #if defined(Q_OS_WIN) @@ -151,10 +152,23 @@ void PluginManager::generateCertificate() arguments.append("-newkey"); arguments.append("rsa:1024"); + QString sslDirPath = QString("%1%2%3") + .arg(m_ProfileDir) + .arg(QDir::separator()) + .arg(kSslDir); + + QDir sslDir(sslDirPath); + if (!sslDir.exists()) { + sslDir.mkdir("."); + } + + QString filename = QString("%1%2%3") + .arg(sslDirPath) + .arg(QDir::separator()) + .arg(kCertificateFilename); + // key output filename arguments.append("-keyout"); - QString filename = m_ProfileDir; - filename.append(QDir::separator()).append(kCertificateFilename); arguments.append(filename); // certificate output filename From f997aea8e74a9225ac320be61eacdb5153efed9e Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 18:51:22 +0100 Subject: [PATCH 39/49] Moved SSL generate code as is into new class #4549 --- src/gui/gui.pro | 8 +- src/gui/src/PluginManager.cpp | 145 ------------------------ src/gui/src/PluginManager.h | 4 +- src/gui/src/PluginWizardPage.cpp | 26 +++-- src/gui/src/PluginWizardPage.h | 4 +- src/gui/src/SslCertificate.cpp | 184 +++++++++++++++++++++++++++++++ src/gui/src/SslCertificate.h | 36 ++++++ 7 files changed, 246 insertions(+), 161 deletions(-) create mode 100644 src/gui/src/SslCertificate.cpp create mode 100644 src/gui/src/SslCertificate.h diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 7f2670be..f519885e 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -56,7 +56,8 @@ SOURCES += src/main.cpp \ src/PluginWizardPage.cpp \ src/PluginManager.cpp \ src/CoreInterface.cpp \ - src/Fingerprint.cpp + src/Fingerprint.cpp \ + src/SslCertificate.cpp HEADERS += src/MainWindow.h \ src/AboutDialog.h \ src/ServerConfig.h \ @@ -99,10 +100,11 @@ HEADERS += src/MainWindow.h \ src/ProcessorArch.h \ src/PluginManager.h \ src/CoreInterface.h \ - src/Fingerprint.h + src/Fingerprint.h \ + src/SslCertificate.h RESOURCES += res/Synergy.qrc RC_FILE = res/win/Synergy.rc -macx { +macx { QMAKE_INFO_PLIST = res/mac/Info.plist TARGET = Synergy QSYNERGY_ICON.files = res/mac/Synergy.icns diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index b32f982c..27224e7e 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -37,15 +37,9 @@ static const char kLinuxProcessorArchDeb32[] = "Linux-i686-deb"; static const char kLinuxProcessorArchDeb64[] = "Linux-x86_64-deb"; static const char kLinuxProcessorArchRpm32[] = "Linux-i686-rpm"; static const char kLinuxProcessorArchRpm64[] = "Linux-x86_64-rpm"; -static QString kCertificateLifetime = "365"; -static QString kCertificateSubjectInfo = "/CN=Synergy"; -static QString kCertificateFilename = "Synergy.pem"; -static QString kSslDir = "SSL"; -static QString kUnixOpenSslCommand = "openssl"; #if defined(Q_OS_WIN) static const char kWinPluginExt[] = ".dll"; -static const char kWinOpenSslBinary[] = "OpenSSL\\openssl.exe"; #elif defined(Q_OS_MAC) static const char kMacPluginPrefix[] = "lib"; @@ -123,104 +117,6 @@ void PluginManager::downloadPlugins() } } -void PluginManager::generateCertificate() -{ - QString openSslProgramFile; - -#if defined(Q_OS_WIN) - openSslProgramFile = QCoreApplication::applicationDirPath(); - openSslProgramFile.append("\\").append(kWinOpenSslBinary); -#else - openSslProgramFile = kUnixOpenSslCommand; -#endif - - QStringList arguments; - - // self signed certificate - arguments.append("req"); - arguments.append("-x509"); - arguments.append("-nodes"); - - // valide duration - arguments.append("-days"); - arguments.append(kCertificateLifetime); - - // subject information - arguments.append("-subj"); - - QString subInfo(kCertificateSubjectInfo); - arguments.append(subInfo); - - // private key - arguments.append("-newkey"); - arguments.append("rsa:1024"); - - QString sslDirPath = QString("%1%2%3") - .arg(m_ProfileDir) - .arg(QDir::separator()) - .arg(kSslDir); - - QDir sslDir(sslDirPath); - if (!sslDir.exists()) { - sslDir.mkdir("."); - } - - QString filename = QString("%1%2%3") - .arg(sslDirPath) - .arg(QDir::separator()) - .arg(kCertificateFilename); - - // key output filename - arguments.append("-keyout"); - arguments.append(filename); - - // certificate output filename - arguments.append("-out"); - arguments.append(filename); - - QStringList environment; - -#if defined(Q_OS_WIN) - environment << QString("OPENSSL_CONF=%1\\OpenSSL\\synergy.conf") - .arg(QCoreApplication::applicationDirPath()); -#endif - - if (!runProgram(openSslProgramFile, arguments, environment)) { - return; - } - - emit info(tr("SSL certificate generated")); - - // generate fingerprint - arguments.clear(); - arguments.append("x509"); - arguments.append("-fingerprint"); - arguments.append("-sha1"); - arguments.append("-noout"); - arguments.append("-in"); - arguments.append(filename); - - if (!runProgram(openSslProgramFile, arguments, environment)) { - return; - } - - // write the standard output into file - filename.clear(); - filename.append(Fingerprint::local().filePath()); - - // only write the fingerprint part - int i = m_standardOutput.indexOf("="); - if (i != -1) { - i++; - QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); - - Fingerprint::local().trust(fingerprint, false); - emit info(tr("SSL fingerprint generated")); - } - - emit generateCertificateFinished(); -} - bool PluginManager::savePlugin() { // create the path if not exist @@ -308,47 +204,6 @@ QString PluginManager::getPluginUrl(const QString& pluginName) return result; } -bool PluginManager::checkOpenSslBinary() -{ - // assume OpenSsl is unavailable on Windows, - // but always available on both Mac and Linux -#if defined(Q_OS_WIN) - return false; -#else - return true; -#endif -} - -bool PluginManager::runProgram( - const QString& program, const QStringList& args, const QStringList& env) -{ - QProcess process; - process.setEnvironment(env); - process.start(program, args); - - bool success = process.waitForStarted(); - - QString standardError; - if (success && process.waitForFinished()) - { - m_standardOutput = process.readAllStandardOutput().trimmed(); - standardError = process.readAllStandardError().trimmed(); - } - - int code = process.exitCode(); - if (!success || code != 0) - { - emit error( - QString("Program failed: %1\n\nCode: %2\nError: %3") - .arg(program) - .arg(process.exitCode()) - .arg(standardError.isEmpty() ? "Unknown" : standardError)); - return false; - } - - return true; -} - QString PluginManager::getPluginOsSpecificName(const QString& pluginName) { QString result = pluginName; diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index bd7fea00..e5a6a33e 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -22,6 +22,7 @@ #include #include +#include "SslCertificate.h" #include "CoreInterface.h" #include "DataDownloader.h" @@ -39,7 +40,6 @@ public: public slots: void downloadPlugins(); - void generateCertificate(); private: bool savePlugin(); @@ -58,7 +58,6 @@ signals: void downloadNext(); void downloadFinished(); void openSslBinaryReady(); - void generateCertificateFinished(); private: QStringList m_PluginList; @@ -68,6 +67,7 @@ private: DataDownloader m_DataDownloader; CoreInterface m_CoreInterface; QString m_standardOutput; + SslCertificate m_SslCertificate; }; #endif // PLUGINMANAGER_H diff --git a/src/gui/src/PluginWizardPage.cpp b/src/gui/src/PluginWizardPage.cpp index 8c0a4d05..9c7e3103 100644 --- a/src/gui/src/PluginWizardPage.cpp +++ b/src/gui/src/PluginWizardPage.cpp @@ -18,6 +18,7 @@ #include "PluginWizardPage.h" #include "ui_PluginWizardPageBase.h" +#include "SslCertificate.h" #include "WebClient.h" #include "PluginManager.h" @@ -29,6 +30,7 @@ PluginWizardPage::PluginWizardPage(AppConfig& appConfig, QWidget *parent) : m_Finished(false), m_pWebClient(NULL), m_pPluginManager(NULL), + m_pSslCertificate(NULL), m_AppConfig(appConfig) { setupUi(this); @@ -36,6 +38,8 @@ PluginWizardPage::PluginWizardPage(AppConfig& appConfig, QWidget *parent) : QMovie *movie = new QMovie(":/res/image/spinning-wheel.gif"); m_pLabelSpinning->setMovie(movie); movie->start(); + + m_pSslCertificate = new SslCertificate(this); } PluginWizardPage::~PluginWizardPage() @@ -47,6 +51,8 @@ PluginWizardPage::~PluginWizardPage() if (m_pPluginManager != NULL) { delete m_pPluginManager; } + + delete m_pSslCertificate; } void PluginWizardPage::changeEvent(QEvent *e) @@ -101,20 +107,20 @@ void PluginWizardPage::finished() void PluginWizardPage::generateCertificate() { - connect(m_pPluginManager, + connect(m_pSslCertificate, SIGNAL(generateCertificateFinished()), this, SLOT(finished())); - connect(m_pPluginManager, + connect(m_pSslCertificate, SIGNAL(generateCertificateFinished()), - m_pPluginManagerThread, + m_pThread, SLOT(quit())); updateStatus(tr("Generating SSL certificate...")); QMetaObject::invokeMethod( - m_pPluginManager, + m_pSslCertificate, "generateCertificate", Qt::QueuedConnection); } @@ -128,7 +134,7 @@ void PluginWizardPage::downloadPlugins() { QStringList pluginList = m_pWebClient->getPluginList(); m_pPluginManager = new PluginManager(pluginList); - m_pPluginManagerThread = new QThread; + m_pThread = new QThread; connect(m_pPluginManager, SIGNAL(error(QString)), @@ -152,12 +158,12 @@ void PluginWizardPage::downloadPlugins() connect(m_pPluginManager, SIGNAL(error(QString)), - m_pPluginManagerThread, + m_pThread, SLOT(quit())); - connect(m_pPluginManagerThread, + connect(m_pThread, SIGNAL(finished()), - m_pPluginManagerThread, + m_pThread, SLOT(deleteLater())); updateStatus( @@ -165,8 +171,8 @@ void PluginWizardPage::downloadPlugins() .arg(pluginList.at(0)) .arg(pluginList.size())); - m_pPluginManager->moveToThread(m_pPluginManagerThread); - m_pPluginManagerThread->start(); + m_pPluginManager->moveToThread(m_pThread); + m_pThread->start(); QMetaObject::invokeMethod( m_pPluginManager, diff --git a/src/gui/src/PluginWizardPage.h b/src/gui/src/PluginWizardPage.h index 0300ebac..b2de1e3b 100644 --- a/src/gui/src/PluginWizardPage.h +++ b/src/gui/src/PluginWizardPage.h @@ -25,6 +25,7 @@ class WebClient; class PluginManager; +class SslCertificate; class PluginWizardPage : public QWizardPage, public Ui::PluginWizardPage { @@ -62,7 +63,8 @@ private: QString m_Password; WebClient* m_pWebClient; PluginManager* m_pPluginManager; - QThread* m_pPluginManagerThread; + SslCertificate* m_pSslCertificate; + QThread* m_pThread; AppConfig& m_AppConfig; }; #endif // PLUGINWIZARDPAGE_H diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp new file mode 100644 index 00000000..08ebd4da --- /dev/null +++ b/src/gui/src/SslCertificate.cpp @@ -0,0 +1,184 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "SslCertificate.h" + +#include "Fingerprint.h" + +#include +#include +#include + +static const char kCertificateLifetime[] = "365"; +static const char kCertificateSubjectInfo[] = "/CN=Synergy"; +static const char kCertificateFilename[] = "Synergy.pem"; +static const char kSslDir[] = "SSL"; +static const char kUnixOpenSslCommand[] = "openssl"; + +#if defined(Q_OS_WIN) +static const char kWinOpenSslBinary[] = "OpenSSL\\openssl.exe"; +#endif + +SslCertificate::SslCertificate(QObject *parent) : + QObject(parent) +{ + m_ProfileDir = m_CoreInterface.getProfileDir(); + if (m_ProfileDir.isEmpty()) { + emit error(tr("Failed to get profile directory.")); + } +} + +bool SslCertificate::checkOpenSslBinary() +{ + // assume OpenSsl is unavailable on Windows, + // but always available on both Mac and Linux +#if defined(Q_OS_WIN) + return false; +#else + return true; +#endif +} + +bool SslCertificate::runProgram( + const QString& program, + const QStringList& args, + const QStringList& env) +{ + QProcess process; + process.setEnvironment(env); + process.start(program, args); + + bool success = process.waitForStarted(); + + QString standardError; + if (success && process.waitForFinished()) + { + m_standardOutput = process.readAllStandardOutput().trimmed(); + standardError = process.readAllStandardError().trimmed(); + } + + int code = process.exitCode(); + if (!success || code != 0) + { + emit error( + QString("Program failed: %1\n\nCode: %2\nError: %3") + .arg(program) + .arg(process.exitCode()) + .arg(standardError.isEmpty() ? "Unknown" : standardError)); + return false; + } + + return true; +} + +void SslCertificate::generateCertificate() +{ + QString openSslProgramFile; + +#if defined(Q_OS_WIN) + openSslProgramFile = QCoreApplication::applicationDirPath(); + openSslProgramFile.append("\\").append(kWinOpenSslBinary); +#else + openSslProgramFile = kUnixOpenSslCommand; +#endif + + QStringList arguments; + + // self signed certificate + arguments.append("req"); + arguments.append("-x509"); + arguments.append("-nodes"); + + // valide duration + arguments.append("-days"); + arguments.append(kCertificateLifetime); + + // subject information + arguments.append("-subj"); + + QString subInfo(kCertificateSubjectInfo); + arguments.append(subInfo); + + // private key + arguments.append("-newkey"); + arguments.append("rsa:1024"); + + QString sslDirPath = QString("%1%2%3") + .arg(m_ProfileDir) + .arg(QDir::separator()) + .arg(kSslDir); + + QDir sslDir(sslDirPath); + if (!sslDir.exists()) { + sslDir.mkdir("."); + } + + QString filename = QString("%1%2%3") + .arg(sslDirPath) + .arg(QDir::separator()) + .arg(kCertificateFilename); + + // key output filename + arguments.append("-keyout"); + arguments.append(filename); + + // certificate output filename + arguments.append("-out"); + arguments.append(filename); + + QStringList environment; + +#if defined(Q_OS_WIN) + environment << QString("OPENSSL_CONF=%1\\OpenSSL\\synergy.conf") + .arg(QCoreApplication::applicationDirPath()); +#endif + + if (!runProgram(openSslProgramFile, arguments, environment)) { + return; + } + + emit info(tr("SSL certificate generated")); + + // generate fingerprint + arguments.clear(); + arguments.append("x509"); + arguments.append("-fingerprint"); + arguments.append("-sha1"); + arguments.append("-noout"); + arguments.append("-in"); + arguments.append(filename); + + if (!runProgram(openSslProgramFile, arguments, environment)) { + return; + } + + // write the standard output into file + filename.clear(); + filename.append(Fingerprint::local().filePath()); + + // only write the fingerprint part + int i = m_standardOutput.indexOf("="); + if (i != -1) { + i++; + QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); + + Fingerprint::local().trust(fingerprint, false); + emit info(tr("SSL fingerprint generated")); + } + + emit generateCertificateFinished(); +} diff --git a/src/gui/src/SslCertificate.h b/src/gui/src/SslCertificate.h new file mode 100644 index 00000000..1e6f8214 --- /dev/null +++ b/src/gui/src/SslCertificate.h @@ -0,0 +1,36 @@ +#ifndef SSLCERTIFICATE_H +#define SSLCERTIFICATE_H + +#include "CoreInterface.h" + +#include + +class SslCertificate : public QObject +{ +Q_OBJECT + +public: + explicit SslCertificate(QObject *parent = 0); + +public slots: + void generateCertificate(); + +signals: + void error(QString e); + void info(QString i); + void generateCertificateFinished(); + +private: + bool checkOpenSslBinary(); + bool runProgram( + const QString& program, + const QStringList& args, + const QStringList& env); + +private: + QString m_ProfileDir; + QString m_standardOutput; + CoreInterface m_CoreInterface; +}; + +#endif // SSLCERTIFICATE_H From a894615ca70bf5ec7abe8d2ea428ff3f22b946ba Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 19:08:03 +0100 Subject: [PATCH 40/49] Fixed ns plugin using old certificate path #4525 --- src/lib/plugin/ns/SecureListenSocket.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/lib/plugin/ns/SecureListenSocket.cpp b/src/lib/plugin/ns/SecureListenSocket.cpp index 86907608..bf8cd7cc 100644 --- a/src/lib/plugin/ns/SecureListenSocket.cpp +++ b/src/lib/plugin/ns/SecureListenSocket.cpp @@ -23,6 +23,7 @@ #include "net/TSocketMultiplexerMethodJob.h" #include "arch/XArch.h" +static const char s_certificateDir[] = { "SSL" }; static const char s_certificateFilename[] = { "Synergy.pem" }; // @@ -60,14 +61,11 @@ SecureListenSocket::accept() setListeningJob(); } - // TODO: customized certificate path - String certificateFilename = ARCH->getProfileDirectory(); -#if SYSAPI_WIN32 - certificateFilename.append("\\"); -#elif SYSAPI_UNIX - certificateFilename.append("/"); -#endif - certificateFilename.append(s_certificateFilename); + String certificateFilename = synergy::string::sprintf( + "%s/%s/%s", + ARCH->getProfileDirectory().c_str(), + s_certificateDir, + s_certificateFilename); bool loaded = socket->loadCertificates(certificateFilename); if (!loaded) { From 7e239c6f714d452a6105bfcf64a4b8378994f0ad Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Mon, 20 Apr 2015 19:26:41 +0100 Subject: [PATCH 41/49] Refactored certificate class Split `generateCertificate` into separtate `generateFingerprint` function, renamed a few functions, removed some unused functions. --- src/gui/src/PluginManager.cpp | 2 +- src/gui/src/PluginManager.h | 3 --- src/gui/src/PluginWizardPage.cpp | 4 ++-- src/gui/src/SslCertificate.h | 33 +++++++++++++++++++++----------- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/gui/src/PluginManager.cpp b/src/gui/src/PluginManager.cpp index 27224e7e..8590a328 100644 --- a/src/gui/src/PluginManager.cpp +++ b/src/gui/src/PluginManager.cpp @@ -133,7 +133,7 @@ bool PluginManager::savePlugin() QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { emit error( - tr("Failed to download plugin '%1' to: %2 \n %3") + tr("Failed to download plugin '%1' to: %2\n%3") .arg(m_PluginList.at(m_DownloadIndex)) .arg(m_PluginDir) .arg(file.errorString())); diff --git a/src/gui/src/PluginManager.h b/src/gui/src/PluginManager.h index e5a6a33e..8426643e 100644 --- a/src/gui/src/PluginManager.h +++ b/src/gui/src/PluginManager.h @@ -44,7 +44,6 @@ public slots: private: bool savePlugin(); QString getPluginUrl(const QString& pluginName); - bool checkOpenSslBinary(); bool runProgram( const QString& program, const QStringList& args, @@ -57,7 +56,6 @@ signals: void info(QString i); void downloadNext(); void downloadFinished(); - void openSslBinaryReady(); private: QStringList m_PluginList; @@ -66,7 +64,6 @@ private: int m_DownloadIndex; DataDownloader m_DataDownloader; CoreInterface m_CoreInterface; - QString m_standardOutput; SslCertificate m_SslCertificate; }; diff --git a/src/gui/src/PluginWizardPage.cpp b/src/gui/src/PluginWizardPage.cpp index 9c7e3103..1e560b0d 100644 --- a/src/gui/src/PluginWizardPage.cpp +++ b/src/gui/src/PluginWizardPage.cpp @@ -108,12 +108,12 @@ void PluginWizardPage::finished() void PluginWizardPage::generateCertificate() { connect(m_pSslCertificate, - SIGNAL(generateCertificateFinished()), + SIGNAL(generateFinished()), this, SLOT(finished())); connect(m_pSslCertificate, - SIGNAL(generateCertificateFinished()), + SIGNAL(generateFinished()), m_pThread, SLOT(quit())); diff --git a/src/gui/src/SslCertificate.h b/src/gui/src/SslCertificate.h index 1e6f8214..e85bc3d4 100644 --- a/src/gui/src/SslCertificate.h +++ b/src/gui/src/SslCertificate.h @@ -1,5 +1,21 @@ -#ifndef SSLCERTIFICATE_H -#define SSLCERTIFICATE_H +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015 Synergy Si Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once #include "CoreInterface.h" @@ -18,19 +34,14 @@ public slots: signals: void error(QString e); void info(QString i); - void generateCertificateFinished(); + void generateFinished(); private: - bool checkOpenSslBinary(); - bool runProgram( - const QString& program, - const QStringList& args, - const QStringList& env); + bool runTool(const QStringList& args); + void generateFingerprint(const QString& certificateFilename); private: QString m_ProfileDir; - QString m_standardOutput; + QString m_ToolOutput; CoreInterface m_CoreInterface; }; - -#endif // SSLCERTIFICATE_H From dbc5da7a48810564b458de11a61758fe315feefd Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 21 Apr 2015 12:55:45 +0100 Subject: [PATCH 42/49] Refactored certificate class (part 2) #4549 --- src/gui/src/SslCertificate.cpp | 217 ++++++++++++++++----------------- 1 file changed, 104 insertions(+), 113 deletions(-) diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp index 08ebd4da..1bb35c50 100644 --- a/src/gui/src/SslCertificate.cpp +++ b/src/gui/src/SslCertificate.cpp @@ -31,6 +31,7 @@ static const char kUnixOpenSslCommand[] = "openssl"; #if defined(Q_OS_WIN) static const char kWinOpenSslBinary[] = "OpenSSL\\openssl.exe"; +static const char kConfigFile[] = "OpenSSL\\synergy.conf"; #endif SslCertificate::SslCertificate(QObject *parent) : @@ -38,147 +39,137 @@ SslCertificate::SslCertificate(QObject *parent) : { m_ProfileDir = m_CoreInterface.getProfileDir(); if (m_ProfileDir.isEmpty()) { - emit error(tr("Failed to get profile directory.")); + emit error(tr("Failed to get profile directory.")); } } -bool SslCertificate::checkOpenSslBinary() +bool SslCertificate::runTool(const QStringList& args) { - // assume OpenSsl is unavailable on Windows, - // but always available on both Mac and Linux + QString program; #if defined(Q_OS_WIN) - return false; + program = QCoreApplication::applicationDirPath(); + program.append("\\").append(kWinOpenSslBinary); #else - return true; + program = kUnixOpenSslCommand; #endif -} -bool SslCertificate::runProgram( - const QString& program, - const QStringList& args, - const QStringList& env) -{ - QProcess process; - process.setEnvironment(env); - process.start(program, args); - bool success = process.waitForStarted(); + QStringList environment; +#if defined(Q_OS_WIN) + environment << QString("OPENSSL_CONF=%1\\%2") + .arg(QCoreApplication::applicationDirPath()) + .arg(kConfigFile); +#endif - QString standardError; - if (success && process.waitForFinished()) - { - m_standardOutput = process.readAllStandardOutput().trimmed(); - standardError = process.readAllStandardError().trimmed(); - } + QProcess process; + process.setEnvironment(environment); + process.start(program, args); - int code = process.exitCode(); - if (!success || code != 0) - { - emit error( - QString("Program failed: %1\n\nCode: %2\nError: %3") - .arg(program) - .arg(process.exitCode()) - .arg(standardError.isEmpty() ? "Unknown" : standardError)); - return false; - } + bool success = process.waitForStarted(); - return true; + QString standardError; + if (success && process.waitForFinished()) + { + m_ToolOutput = process.readAllStandardOutput().trimmed(); + standardError = process.readAllStandardError().trimmed(); + } + + int code = process.exitCode(); + if (!success || code != 0) + { + emit error( + QString("SSL tool failed: %1\n\nCode: %2\nError: %3") + .arg(program) + .arg(process.exitCode()) + .arg(standardError.isEmpty() ? "Unknown" : standardError)); + return false; + } + + return true; } void SslCertificate::generateCertificate() { - QString openSslProgramFile; + QStringList arguments; -#if defined(Q_OS_WIN) - openSslProgramFile = QCoreApplication::applicationDirPath(); - openSslProgramFile.append("\\").append(kWinOpenSslBinary); -#else - openSslProgramFile = kUnixOpenSslCommand; -#endif + // self signed certificate + arguments.append("req"); + arguments.append("-x509"); + arguments.append("-nodes"); - QStringList arguments; + // valide duration + arguments.append("-days"); + arguments.append(kCertificateLifetime); - // self signed certificate - arguments.append("req"); - arguments.append("-x509"); - arguments.append("-nodes"); + // subject information + arguments.append("-subj"); - // valide duration - arguments.append("-days"); - arguments.append(kCertificateLifetime); + QString subInfo(kCertificateSubjectInfo); + arguments.append(subInfo); - // subject information - arguments.append("-subj"); + // private key + arguments.append("-newkey"); + arguments.append("rsa:1024"); - QString subInfo(kCertificateSubjectInfo); - arguments.append(subInfo); + QString sslDirPath = QString("%1%2%3") + .arg(m_ProfileDir) + .arg(QDir::separator()) + .arg(kSslDir); - // private key - arguments.append("-newkey"); - arguments.append("rsa:1024"); + QDir sslDir(sslDirPath); + if (!sslDir.exists()) { + sslDir.mkdir("."); + } - QString sslDirPath = QString("%1%2%3") - .arg(m_ProfileDir) - .arg(QDir::separator()) - .arg(kSslDir); + QString filename = QString("%1%2%3") + .arg(sslDirPath) + .arg(QDir::separator()) + .arg(kCertificateFilename); - QDir sslDir(sslDirPath); - if (!sslDir.exists()) { - sslDir.mkdir("."); - } + // key output filename + arguments.append("-keyout"); + arguments.append(filename); - QString filename = QString("%1%2%3") - .arg(sslDirPath) - .arg(QDir::separator()) - .arg(kCertificateFilename); + // certificate output filename + arguments.append("-out"); + arguments.append(filename); - // key output filename - arguments.append("-keyout"); - arguments.append(filename); + if (!runTool(arguments)) { + return; + } - // certificate output filename - arguments.append("-out"); - arguments.append(filename); + emit info(tr("SSL certificate generated.")); - QStringList environment; + generateFingerprint(filename); -#if defined(Q_OS_WIN) - environment << QString("OPENSSL_CONF=%1\\OpenSSL\\synergy.conf") - .arg(QCoreApplication::applicationDirPath()); -#endif - - if (!runProgram(openSslProgramFile, arguments, environment)) { - return; - } - - emit info(tr("SSL certificate generated")); - - // generate fingerprint - arguments.clear(); - arguments.append("x509"); - arguments.append("-fingerprint"); - arguments.append("-sha1"); - arguments.append("-noout"); - arguments.append("-in"); - arguments.append(filename); - - if (!runProgram(openSslProgramFile, arguments, environment)) { - return; - } - - // write the standard output into file - filename.clear(); - filename.append(Fingerprint::local().filePath()); - - // only write the fingerprint part - int i = m_standardOutput.indexOf("="); - if (i != -1) { - i++; - QString fingerprint = m_standardOutput.mid(i, m_standardOutput.size() - i); - - Fingerprint::local().trust(fingerprint, false); - emit info(tr("SSL fingerprint generated")); - } - - emit generateCertificateFinished(); + emit generateFinished(); +} + +void SslCertificate::generateFingerprint(const QString& certificateFilename) +{ + QStringList arguments; + arguments.append("x509"); + arguments.append("-fingerprint"); + arguments.append("-sha1"); + arguments.append("-noout"); + arguments.append("-in"); + arguments.append(certificateFilename); + + if (!runTool(arguments)) { + return; + } + + // find the fingerprint from the tool output + int i = m_ToolOutput.indexOf("="); + if (i != -1) { + i++; + QString fingerprint = m_ToolOutput.mid( + i, m_ToolOutput.size() - i); + + Fingerprint::local().trust(fingerprint, false); + emit info(tr("SSL fingerprint generated.")); + } + else { + emit error(tr("Failed to find SSL fingerprint.")); + } } From d184be31b5e49a12d839bd7758f729ae5eef5a95 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 21 Apr 2015 14:48:28 +0100 Subject: [PATCH 43/49] Fixed: SSL dir not created on Mac #4551 --- src/gui/src/SslCertificate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/src/SslCertificate.cpp b/src/gui/src/SslCertificate.cpp index 1bb35c50..eee38fc6 100644 --- a/src/gui/src/SslCertificate.cpp +++ b/src/gui/src/SslCertificate.cpp @@ -118,7 +118,7 @@ void SslCertificate::generateCertificate() QDir sslDir(sslDirPath); if (!sslDir.exists()) { - sslDir.mkdir("."); + sslDir.mkpath("."); } QString filename = QString("%1%2%3") From f56d06d95d0614fb828cb6b9c823bedf127f73d9 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 21 Apr 2015 16:25:55 +0100 Subject: [PATCH 44/49] Disabled auto-hide feature #4390 --- src/gui/src/MainWindow.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 6ca2d549..16c92454 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -553,14 +553,6 @@ void MainWindow::startSynergy() if (desktopMode) { - if (!appConfig().startedBefore()) { - QMessageBox::information( - this, "Synergy", - tr("Synergy will be minimized to the notification " - "area. This will happen automatically when Synergy " - "starts.")); - } - synergyProcess()->start(app, args); if (!synergyProcess()->waitForStarted()) { @@ -818,12 +810,6 @@ void MainWindow::setSynergyState(qSynergyState state) setIcon(state); m_SynergyState = state; - - // if in desktop mode, hide synergy. in service mode the gui can - // just be closed. - if ((appConfig().processMode() == Desktop) && (state == synergyConnected)) { - hide(); - } } void MainWindow::setVisible(bool visible) From 423d698436d9b6079a2086ef6bf8bd1e3037d867 Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Tue, 21 Apr 2015 16:46:05 +0100 Subject: [PATCH 45/49] Fixed secure socket using old trusted fingerprint path #4525 --- src/lib/plugin/ns/SecureSocket.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index ccc3ec01..2de8261e 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -36,10 +36,10 @@ #define MAX_ERROR_SIZE 65535 -static const char kFingerprintDirName[] = "ssl/fingerprints"; -//static const char kFingerprintLocalFilename[] = "local.txt"; -static const char kFingerprintTrustedServersFilename[] = "trusted-servers.txt"; -//static const char kFingerprintTrustedClientsFilename[] = "trusted-clients.txt"; +static const char kFingerprintDirName[] = "SSL/Fingerprints"; +//static const char kFingerprintLocalFilename[] = "Local.txt"; +static const char kFingerprintTrustedServersFilename[] = "TrustedServers.txt"; +//static const char kFingerprintTrustedClientsFilename[] = "TrustedClients.txt"; struct Ssl { SSL_CTX* m_context; @@ -493,7 +493,7 @@ SecureSocket::verifyCertFingerprint() file.open(trustedServersFilename.c_str()); bool isValid = false; - while (!file.eof()) { + while (!file.eof() && file.is_open()) { getline(file,fileLine); if (!fileLine.empty()) { if (fileLine.compare(fingerprint) == 0) { From 018480412aad0648335213faa8699f669df28f82 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Tue, 21 Apr 2015 16:54:49 +0100 Subject: [PATCH 46/49] Stopped retry when fatal error happened in secure socket #4553 --- src/lib/plugin/ns/SecureSocket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 2de8261e..0a36daab 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -297,7 +297,6 @@ SecureSocket::secureConnect(int socket) } else { LOG((CLOG_ERR "failed to verify server certificate fingerprint")); - sendEvent(getEvents()->forISocket().stopRetry()); disconnect(); } } @@ -435,6 +434,7 @@ SecureSocket::getError() void SecureSocket::disconnect() { + sendEvent(getEvents()->forISocket().stopRetry()); sendEvent(getEvents()->forISocket().disconnected()); sendEvent(getEvents()->forIStream().inputShutdown()); } From 363dc78ca8a8b4c4a135bebaca2dd81d8312a1b3 Mon Sep 17 00:00:00 2001 From: XinyuHou Date: Tue, 21 Apr 2015 17:56:01 +0100 Subject: [PATCH 47/49] Updated local fingerprint after wizard is finished #4557 --- src/gui/src/MainWindow.cpp | 23 ++++++++++++++--------- src/gui/src/MainWindow.h | 1 + src/gui/src/SetupWizard.cpp | 1 + 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 16c92454..e54c9c37 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -135,15 +135,7 @@ MainWindow::MainWindow(QSettings& settings, AppConfig& appConfig) : m_pLabelPadlock->hide(); - if (Fingerprint::local().fileExists()) { - m_pLabelFingerprint->setVisible(true); - m_pLabelLocalFingerprint->setVisible(true); - m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst()); - } - else { - m_pLabelFingerprint->setVisible(false); - m_pLabelLocalFingerprint->setVisible(false); - } + updateLocalFingerprint(); } MainWindow::~MainWindow() @@ -940,6 +932,19 @@ void MainWindow::setEdition(int type) setWindowTitle(title); } +void MainWindow::updateLocalFingerprint() +{ + if (Fingerprint::local().fileExists()) { + m_pLabelFingerprint->setVisible(true); + m_pLabelLocalFingerprint->setVisible(true); + m_pLabelLocalFingerprint->setText(Fingerprint::local().readFirst()); + } + else { + m_pLabelFingerprint->setVisible(false); + m_pLabelLocalFingerprint->setVisible(false); + } +} + void MainWindow::on_m_pGroupClient_toggled(bool on) { m_pGroupServer->setChecked(!on); diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index 9ab1b17b..40bb7975 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -106,6 +106,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindowBase void updateZeroconfService(); void serverDetected(const QString name); void setEdition(int type); + void updateLocalFingerprint(); public slots: void appendLogRaw(const QString& text); diff --git a/src/gui/src/SetupWizard.cpp b/src/gui/src/SetupWizard.cpp index bc9d1ca3..803725be 100644 --- a/src/gui/src/SetupWizard.cpp +++ b/src/gui/src/SetupWizard.cpp @@ -169,6 +169,7 @@ void SetupWizard::accept() appConfig.setEdition(m_Edition); } m_MainWindow.setEdition(m_Edition); + m_MainWindow.updateLocalFingerprint(); settings.sync(); From 366f813a2cc317dda2d90386ec42eef49746833c Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 21 Apr 2015 18:46:32 +0100 Subject: [PATCH 48/49] ChangeLog for v1.7.1-stable --- ChangeLog | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1eb0d7f2..77622141 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +v1.7.1 +====== +Bug #3784 - Double click & drag doesn't select words on client +Bug #3052 - Triple-click (select line) does not work +Bug #4367 - Duplicate Alt-S Keyboard Shortcuts on Gui +Bug #4554 - Server unable to accept new SSL connection +Bug #4553 - SSL handshake failure error causes GUI to crash +Bug #4551 - Plugin wizard doesn't create SSL directory +Bug #4548 - Severe code duplication in fingerprint logic +Bug #4547 - Windows server crashes when client fingerprint dialog open +Bug #4539 - Mac client dies when server has SSL_ERROR_SSL +Bug #4537 - Plugin wizard doesn't complete but finish button enabled +Bug #4535 - Server crashes on shut down after multiple connections failed +Bug #4528 - Error SSL_ERROR_SSL is logged on unknown error +Bug #4527 - Server fingerprint dialog on client GUI keeps showing +Bug #4469 - GUI crashes on Windows when generating certificate +Bug #4410 - SSL_ERROR_SSL (unknown protocol) on Mac client +Bug #4409 - SSL_ERROR_SSL (unknown alert type) on Windows 8.1 client +Bug #4557 - GUI doesn't show local fingerprint on fresh install +Enhancement #4522 - SSL server fingerprint verification from client +Enhancement #4526 - Display local fingerprint on server GUI +Enhancement #4549 - Extract SSL certificate and fingerprint generate function +Enhancement #4546 - Redistribute OpenSSL on Windows with installer +Enhancement #4540 - Enable Network Security checkbox only when ns plugin exists +Enhancement #4525 - Reorganize app data directory +Enhancement #4390 - Disable GUI auto-hide by default + 1.7.0 ===== Enhancement #4313 - SSL encrypted secure connection From c4f7c9be701d6111c2dd1616de11cd29d600a578 Mon Sep 17 00:00:00 2001 From: Nick Bolton Date: Tue, 21 Apr 2015 18:49:49 +0100 Subject: [PATCH 49/49] Version to 1.7.2 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af61440e..349cd9e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ # Version number for Synergy set(VERSION_MAJOR 1) set(VERSION_MINOR 7) -set(VERSION_REV 1) +set(VERSION_REV 2) set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REV}") cmake_minimum_required(VERSION 2.6)