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:
parent
6e2ccb8f8d
commit
5dfe4aa0b5
|
@ -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&) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
|
|
||||||
#include "synergy/ClientArgs.h"
|
#include "synergy/ClientArgs.h"
|
||||||
|
|
||||||
ClientArgs::ClientArgs() :
|
CClientArgs::CClientArgs() :
|
||||||
m_yscroll(0)
|
m_yscroll(0),
|
||||||
|
m_certFingerprint()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,5 +26,6 @@ public:
|
||||||
ClientArgs();
|
ClientArgs();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int m_yscroll;
|
int m_yscroll;
|
||||||
|
CString m_certFingerprint;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue