Added verification of server certificate fingerprint #4522

Conflicts:
	src/lib/mt/Thread.cpp
	src/lib/plugin/ns/SecureSocket.cpp
	src/lib/synergy/ClientArgs.cpp
This commit is contained in:
Xinyu Hou 2015-04-01 16:04:10 +01:00 committed by XinyuHou
parent 6e2ccb8f8d
commit 5dfe4aa0b5
6 changed files with 92 additions and 10 deletions

View File

@ -160,7 +160,6 @@ Thread::threadFunc(void* vjob)
} }
catch (XSocket& e) { catch (XSocket& e) {
// client called cancel()
LOG((CLOG_DEBUG "%s", e.what())); LOG((CLOG_DEBUG "%s", e.what()));
} }
catch (XThreadCancel&) { catch (XThreadCancel&) {

View File

@ -23,11 +23,13 @@
#include "arch/XArch.h" #include "arch/XArch.h"
#include "base/Log.h" #include "base/Log.h"
#include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <memory> #include <memory>
#include <sstream>
#include <iomanip>
#include <fstream>
// //
// SecureSocket // SecureSocket
@ -40,11 +42,14 @@ struct Ssl {
SSL* m_ssl; SSL* m_ssl;
}; };
SecureSocket::SecureSocket( bool CSecureSocket::s_verifyFingerprintFailed = false;
CSecureSocket::CSecureSocket(
IEventQueue* events, IEventQueue* events,
SocketMultiplexer* socketMultiplexer) : CSocketMultiplexer* socketMultiplexer) :
TCPSocket(events, socketMultiplexer), CTCPSocket(events, socketMultiplexer),
m_secureReady(false) m_secureReady(false),
m_certFingerprint()
{ {
} }
@ -169,6 +174,8 @@ SecureSocket::loadCertificates(const char* filename)
} }
} }
const char test[] = "/Users/xinyu/serverCertificateFingerprint.txt";
void void
SecureSocket::initContext(bool server) SecureSocket::initContext(bool server)
{ {
@ -197,6 +204,11 @@ SecureSocket::initContext(bool server)
if (m_ssl->m_context == NULL) { if (m_ssl->m_context == NULL) {
showError(); showError();
} }
if (!server) {
//void* p = reinterpret_cast<void*>(const_cast<char*>(m_certFingerprint.c_str()));
SSL_CTX_set_cert_verify_callback(m_ssl->m_context, CSecureSocket::verifyCertFingerprint, (void*)test);
}
} }
void void
@ -261,6 +273,10 @@ SecureSocket::secureConnect(int socket)
m_secureReady = !retry; m_secureReady = !retry;
if (s_verifyFingerprintFailed) {
throwError("failed to verify server certificate fingerprint");
}
if (m_secureReady) { if (m_secureReady) {
LOG((CLOG_INFO "connected to secure socket")); LOG((CLOG_INFO "connected to secure socket"));
showCertificate(); showCertificate();
@ -366,7 +382,7 @@ SecureSocket::throwError(const char* reason)
String error = getError(); String error = getError();
if (!error.empty()) { if (!error.empty()) {
throw XSocket(synergy::string::sprintf( throw XSocket(synergy::string::sprintf(
"%s: %s", reason, error.c_str())); "%s: %s", reason, error.c_str()));
} }
else { else {
throw XSocket(reason); throw XSocket(reason);
@ -419,3 +435,54 @@ SecureSocket::serviceAccept(ISocketMultiplexerJob* job,
return retry ? job : newJob(); 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<char*>(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;
}

View File

@ -20,6 +20,8 @@
#include "net/TCPSocket.h" #include "net/TCPSocket.h"
#include "net/XSocket.h" #include "net/XSocket.h"
#include <openssl/ssl.h>
class IEventQueue; class IEventQueue;
class SocketMultiplexer; class SocketMultiplexer;
class ISocketMultiplexerJob; class ISocketMultiplexerJob;
@ -71,7 +73,15 @@ private:
serviceAccept(ISocketMultiplexerJob*, serviceAccept(ISocketMultiplexerJob*,
bool, bool, bool); bool, bool, bool);
private:
static int verifyCertFingerprint(X509_STORE_CTX* ctx, void* arg);
private: private:
Ssl* m_ssl; Ssl* m_ssl;
bool m_secureReady; bool m_secureReady;
CString m_certFingerprint;
private:
static bool s_verifyFingerprintFailed;
}; };

View File

@ -89,6 +89,10 @@ ArgParser::parseClientArgs(ClientArgs& args, int argc, const char* const* argv)
// define scroll // define scroll
args.m_yscroll = atoi(argv[++i]); args.m_yscroll = atoi(argv[++i]);
} }
else if (isArg(i, argc, argv, NULL, "--certificate-fingerprint", 1)) {
// define scroll
args.m_certFingerprint = argv[++i];
}
else { else {
if (i + 1 == argc) { if (i + 1 == argc) {
args.m_synergyAddress = argv[i]; args.m_synergyAddress = argv[i];

View File

@ -17,7 +17,8 @@
#include "synergy/ClientArgs.h" #include "synergy/ClientArgs.h"
ClientArgs::ClientArgs() : CClientArgs::CClientArgs() :
m_yscroll(0) m_yscroll(0),
m_certFingerprint()
{ {
} }

View File

@ -26,5 +26,6 @@ public:
ClientArgs(); ClientArgs();
public: public:
int m_yscroll; int m_yscroll;
CString m_certFingerprint;
}; };