From 5dfe4aa0b515ab453e430442ac8e7c88586c83d9 Mon Sep 17 00:00:00 2001 From: Xinyu Hou Date: Wed, 1 Apr 2015 16:04:10 +0100 Subject: [PATCH] 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; };