diff --git a/src/common/net/Client.cpp b/src/common/net/Client.cpp index d789ac89..b039727d 100644 --- a/src/common/net/Client.cpp +++ b/src/common/net/Client.cpp @@ -186,11 +186,23 @@ bool Client::disconnect() } +const char *Client::tlsFingerprint() const +{ +# ifndef XMRIG_NO_TLS + if (isTLS() && m_pool.fingerprint() == nullptr) { + return m_tls->fingerprint(); + } +# endif + + return nullptr; +} + + const char *Client::tlsVersion() const { # ifndef XMRIG_NO_TLS if (isTLS()) { - return m_tls->tlsVersion(); + return m_tls->version(); } # endif diff --git a/src/common/net/Client.h b/src/common/net/Client.h index b3879885..55105c0b 100644 --- a/src/common/net/Client.h +++ b/src/common/net/Client.h @@ -69,6 +69,7 @@ public: ~Client(); bool disconnect(); + const char *tlsFingerprint() const; const char *tlsVersion() const; int64_t submit(const JobResult &result); void connect(); diff --git a/src/common/net/Tls.cpp b/src/common/net/Tls.cpp index 2cfc0e52..182d86ff 100644 --- a/src/common/net/Tls.cpp +++ b/src/common/net/Tls.cpp @@ -32,9 +32,15 @@ #include "common/log/Log.h" +#ifdef _MSC_VER +# define strncasecmp(x,y,z) _strnicmp(x,y,z) +#endif + + Client::Tls::Tls(Client *client) : m_ready(false), m_buf(), + m_fingerprint(), m_client(client), m_ssl(nullptr) { @@ -88,7 +94,13 @@ bool Client::Tls::send(const char *data, size_t size) } -const char *Client::Tls::tlsVersion() const +const char *Client::Tls::fingerprint() const +{ + return m_ready ? m_fingerprint : nullptr; +} + + +const char *Client::Tls::version() const { return m_ready ? SSL_get_version(m_ssl) : nullptr; } @@ -104,13 +116,15 @@ void Client::Tls::read(const char *data, size_t size) if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) { send(); } else if (rc == 1) { - if (!verify()) { - LOG_ERR("[%s] TLS certificate verification failed", m_client->m_pool.url()); + X509 *cert = SSL_get_peer_certificate(m_ssl); + if (!verify(cert)) { + X509_free(cert); m_client->close(); return; } + X509_free(cert); m_ready = true; m_client->login(); } @@ -131,12 +145,46 @@ bool Client::Tls::send() } -bool Client::Tls::verify() +bool Client::Tls::verify(X509 *cert) { - X509* cert = SSL_get_peer_certificate(m_ssl); if (cert == nullptr) { + LOG_ERR("[%s] Failed to get server certificate", m_client->m_pool.url()); + + return false; + } + + if (!verifyFingerprint(cert)) { + LOG_ERR("[%s] Failed to verify server certificate fingerprint", m_client->m_pool.url()); + + const char *fingerprint = m_client->m_pool.fingerprint(); + if (strlen(m_fingerprint) == 64 && fingerprint != nullptr) { + LOG_ERR("\"%s\" was given", m_fingerprint); + LOG_ERR("\"%s\" was configured", fingerprint); + } + return false; } return true; } + + +bool Client::Tls::verifyFingerprint(X509 *cert) +{ + const EVP_MD *digest = EVP_get_digestbyname("sha256"); + if (digest == nullptr) { + return false; + } + + unsigned char md[EVP_MAX_MD_SIZE]; + unsigned int dlen; + + if (X509_digest(cert, digest, md, &dlen) != 1) { + return false; + } + + Job::toHex(md, 32, m_fingerprint); + const char *fingerprint = m_client->m_pool.fingerprint(); + + return fingerprint == nullptr || strncasecmp(m_fingerprint, fingerprint, 64) == 0; +} diff --git a/src/common/net/Tls.h b/src/common/net/Tls.h index ee3b59ef..6e38f32f 100644 --- a/src/common/net/Tls.h +++ b/src/common/net/Tls.h @@ -39,17 +39,20 @@ public: bool handshake(); bool send(const char *data, size_t size); - const char *tlsVersion() const; + const char *fingerprint() const; + const char *version() const; void read(const char *data, size_t size); private: bool send(); - bool verify(); + bool verify(X509 *cert); + bool verifyFingerprint(X509 *cert); BIO *m_readBio; BIO *m_writeBio; bool m_ready; char m_buf[1024 * 2]; + char m_fingerprint[32 * 2 + 8]; Client *m_client; SSL *m_ssl; SSL_CTX *m_ctx; diff --git a/src/net/Network.cpp b/src/net/Network.cpp index 9997f7e7..703e0ccf 100644 --- a/src/net/Network.cpp +++ b/src/net/Network.cpp @@ -102,9 +102,14 @@ void Network::onActive(IStrategy *strategy, Client *client) m_state.setPool(client->host(), client->port(), client->ip()); const char *tlsVersion = client->tlsVersion(); - LOG_INFO(isColors() ? WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " \x1B[01;30m%s " + LOG_INFO(isColors() ? WHITE_BOLD("use pool ") CYAN_BOLD("%s:%d ") GREEN_BOLD("%s") " \x1B[1;30m%s " : "use pool %s:%d %s %s", client->host(), client->port(), tlsVersion ? tlsVersion : "", client->ip()); + + const char *fingerprint = client->tlsFingerprint(); + if (fingerprint != nullptr) { + LOG_INFO("\x1B[1;30mfingerprint (SHA-256): \"%s\"", fingerprint); + } }