Initial TLS support.

This commit is contained in:
XMRig 2018-09-16 03:06:54 +03:00
parent 812cd9760f
commit 14ac7b556e
16 changed files with 494 additions and 121 deletions

View file

@ -6,6 +6,7 @@ option(WITH_AEON "CryptoNight-Lite support" ON)
option(WITH_SUMO "CryptoNight-Heavy support" ON)
option(WITH_HTTPD "HTTP REST API" ON)
option(WITH_DEBUG_LOG "Enable debug log output" OFF)
option(WITH_TLS "Enable OpenSSL support" OFF)
option(BUILD_STATIC "Build static binary" OFF)
include (CheckIncludeFile)
@ -194,6 +195,8 @@ else()
endif()
endif()
include(cmake/OpenSSL.cmake)
CHECK_INCLUDE_FILE (syslog.h HAVE_SYSLOG_H)
if (HAVE_SYSLOG_H)
add_definitions(/DHAVE_SYSLOG_H)
@ -233,6 +236,7 @@ if (WITH_HTTPD)
message(FATAL_ERROR "microhttpd NOT found: use `-DWITH_HTTPD=OFF` to build without http deamon support")
endif()
else()
set(HTTPD_SOURCES "")
set(MHD_LIBRARY "")
add_definitions(/DXMRIG_NO_HTTPD)
add_definitions(/DXMRIG_NO_API)
@ -250,5 +254,5 @@ if (WITH_DEBUG_LOG)
add_definitions(/DAPP_DEBUG)
endif()
add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES})
target_link_libraries(${PROJECT_NAME} ${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})
add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES} ${SOURCES_OS} ${SOURCES_CPUID} ${HEADERS_CRYPTO} ${SOURCES_CRYPTO} ${SOURCES_SYSLOG} ${HTTPD_SOURCES} ${TLS_SOURCES})
target_link_libraries(${PROJECT_NAME} ${OPENSSL_LIBRARIES} ${UV_LIBRARIES} ${MHD_LIBRARY} ${EXTRA_LIBS} ${CPUID_LIB})

18
cmake/OpenSSL.cmake Normal file
View file

@ -0,0 +1,18 @@
if (WITH_TLS)
set(OPENSSL_ROOT_DIR ${XMRIG_DEPS})
set(OPENSSL_USE_STATIC_LIBS TRUE)
set(OPENSSL_MSVC_STATIC_RT TRUE)
find_package(OpenSSL)
if (OPENSSL_FOUND)
set(TLS_SOURCES src/common/net/Tls.h src/common/net/Tls.cpp)
include_directories(${OPENSSL_INCLUDE_DIR})
else()
message(FATAL_ERROR "OpenSSL NOT found: use `-DWITH_TLS=OFF` to build without TLS support")
endif()
else()
set(TLS_SOURCES "")
set(OPENSSL_LIBRARIES "")
add_definitions(/DXMRIG_NO_TLS)
endif()

View file

@ -26,6 +26,12 @@
#include <uv.h>
#ifndef XMRIG_NO_TLS
# include <openssl/ssl.h>
# include <openssl/err.h>
#endif
#include "Platform.h"
@ -61,3 +67,23 @@ const char *Platform::defaultConfigName()
*m_defaultConfigName = '\0';
return nullptr;
}
void Platform::init(const char *userAgent)
{
# ifndef XMRIG_NO_TLS
SSL_library_init();
SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
SSL_load_error_strings();
OpenSSL_add_all_digests();
# endif
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}

View file

@ -21,8 +21,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
#ifndef XMRIG_PLATFORM_H
#define XMRIG_PLATFORM_H
#include <stdint.h>
@ -43,9 +43,11 @@ public:
static inline const char *userAgent() { return m_userAgent.data(); }
private:
static char *createUserAgent();
static char m_defaultConfigName[520];
static xmrig::c_str m_userAgent;
};
#endif /* __PLATFORM_H__ */
#endif /* XMRIG_PLATFORM_H */

View file

@ -38,7 +38,7 @@
#endif
static inline char *createUserAgent()
char *Platform::createUserAgent()
{
const size_t max = 160;
@ -65,17 +65,6 @@ bool Platform::setThreadAffinity(uint64_t cpu_id)
}
void Platform::init(const char *userAgent)
{
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}
void Platform::setProcessPriority(int priority)
{

View file

@ -52,7 +52,7 @@ typedef cpuset_t cpu_set_t;
#endif
static inline char *createUserAgent()
char *Platform::createUserAgent()
{
const size_t max = 160;
@ -92,23 +92,11 @@ bool Platform::setThreadAffinity(uint64_t cpu_id)
}
void Platform::init(const char *userAgent)
{
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}
void Platform::setProcessPriority(int priority)
{
}
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {

View file

@ -55,7 +55,7 @@ static inline OSVERSIONINFOEX winOsVersion()
}
static inline char *createUserAgent()
char *Platform::createUserAgent()
{
const auto osver = winOsVersion();
const size_t max = 160;
@ -94,17 +94,6 @@ bool Platform::setThreadAffinity(uint64_t cpu_id)
}
void Platform::init(const char *userAgent)
{
if (userAgent) {
m_userAgent = userAgent;
}
else {
m_userAgent = createUserAgent();
}
}
void Platform::setProcessPriority(int priority)
{
if (priority == -1) {

View file

@ -157,6 +157,10 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable)
m_pools.back().setKeepAlive(enable ? Pool::kKeepAliveTimeout : 0);
break;
case TlsKey: /* --tls */
m_pools.back().setTLS(enable);
break;
# ifndef XMRIG_PROXY_PROJECT
case NicehashKey: /* --nicehash */
m_pools.back().setNicehash(enable);
@ -235,6 +239,10 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
m_pools.back().setRigId(arg);
break;
case FingerprintKey: /* --tls-fingerprint */
m_pools.back().setFingerprint(arg);
break;
case VariantKey: /* --variant */
m_pools.back().algorithm().parseVariant(arg);
break;
@ -269,6 +277,7 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
case SyslogKey: /* --syslog */
case KeepAliveKey: /* --keepalive */
case NicehashKey: /* --nicehash */
case TlsKey: /* --tls */
case ApiIPv6Key: /* --api-ipv6 */
case DryRunKey: /* --dry-run */
return parseBoolean(key, true);

View file

@ -63,6 +63,8 @@ public:
VerboseKey = 1100,
VersionKey = 'V',
WatchKey = 1105,
TlsKey = 1013,
FingerprintKey = 1014,
// xmrig common
CPUPriorityKey = 1021,
@ -80,17 +82,13 @@ public:
HardwareAESKey = 1011,
// xmrig amd
OclPlatformKey = 1400,
OclAffinityKey = 1401,
OclDevicesKey = 1402,
OclLaunchKey = 1403,
OclCacheKey = 1404,
OclPrintKey = 1405,
OclLoaderKey = 1406,
OclSridedIndexKey = 1407,
OclMemChunkKey = 1408,
OclUnrollKey = 1409,
OclCompModeKey = 1410,
OclPlatform = 1400,
OclAffinity = 1401,
OclDevices = 1402,
OclLaunch = 1403,
OclCache = 1404,
OclPrint = 1405,
OclLoader = 1406,
// xmrig-proxy
AccessLogFileKey = 'A',

View file

@ -29,6 +29,13 @@
#include <utility>
#ifndef XMRIG_NO_TLS
# include <openssl/ssl.h>
# include <openssl/err.h>
# include "common/net/Tls.h"
#endif
#include "common/interfaces/IClientListener.h"
#include "common/log/Log.h"
#include "common/net/Client.h"
@ -48,6 +55,17 @@ int64_t Client::m_sequence = 1;
xmrig::Storage<Client> Client::m_storage;
#ifdef APP_DEBUG
static const char *states[] = {
"unconnected",
"host-lookup",
"connecting",
"connected",
"closing"
};
#endif
Client::Client(int id, const char *agent, IClientListener *listener) :
m_ipv6(false),
m_nicehash(false),
@ -61,6 +79,7 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_failures(0),
m_recvBufPos(0),
m_state(UnconnectedState),
m_tls(nullptr),
m_expire(0),
m_jobs(0),
m_keepAlive(0),
@ -92,6 +111,12 @@ Client::~Client()
void Client::connect()
{
# ifndef XMRIG_NO_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host());
}
@ -122,6 +147,7 @@ void Client::deleteLater()
}
void Client::setPool(const Pool &pool)
{
if (!pool.isValid()) {
@ -160,6 +186,12 @@ bool Client::disconnect()
}
bool Client::isTLS() const
{
return m_pool.isTLS() && m_tls;
}
int64_t Client::submit(const JobResult &result)
{
using namespace rapidjson;
@ -330,6 +362,39 @@ bool Client::parseLogin(const rapidjson::Value &result, int *code)
}
bool Client::send(BIO *bio)
{
# ifndef XMRIG_NO_TLS
uv_buf_t buf;
buf.len = BIO_get_mem_data(bio, &buf.base);
if (buf.len == 0) {
return true;
}
LOG_DEBUG("[%s] TLS send (%d bytes)", m_pool.url(), static_cast<int>(buf.len));
bool result = false;
if (state() == ConnectedState && uv_is_writable(m_stream)) {
result = uv_try_write(m_stream, &buf, 1) > 0;
if (!result) {
close();
}
}
else {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
}
BIO_reset(bio);
return result;
# else
return false;
# endif
}
bool Client::verifyAlgorithm(const xmrig::Algorithm &algorithm) const
{
# ifdef XMRIG_PROXY_PROJECT
@ -404,16 +469,27 @@ int64_t Client::send(const rapidjson::Document &doc)
int64_t Client::send(size_t size)
{
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf);
if (state() != ConnectedState || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
return -1;
# ifndef XMRIG_NO_TLS
if (isTLS()) {
if (!m_tls->send(m_sendBuf, size)) {
return -1;
}
}
else
# endif
{
if (state() != ConnectedState || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", m_pool.url(), m_state);
return -1;
}
uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
if (uv_try_write(m_stream, &buf, 1) < 0) {
close();
return -1;
if (uv_try_write(m_stream, &buf, 1) < 0) {
close();
return -1;
}
}
m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
@ -463,6 +539,22 @@ void Client::connect(sockaddr *addr)
}
void Client::handshake()
{
# ifndef XMRIG_NO_TLS
if (isTLS()) {
m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
m_tls->handshake();
}
else
# endif
{
login();
}
}
void Client::login()
{
using namespace rapidjson;
@ -511,6 +603,13 @@ void Client::onClose()
m_socket = nullptr;
setState(UnconnectedState);
# ifndef XMRIG_NO_TLS
if (m_tls) {
delete m_tls;
m_tls = nullptr;
}
# endif
reconnect();
}
@ -665,6 +764,35 @@ void Client::ping()
}
void Client::read()
{
char* end;
char* start = m_recvBuf.base;
size_t remaining = m_recvBufPos;
while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
end++;
size_t len = end - start;
parse(start, len);
remaining -= len;
start = end;
}
if (remaining == 0) {
m_recvBufPos = 0;
return;
}
if (start == m_recvBuf.base) {
return;
}
memcpy(m_recvBuf.base, start, remaining);
m_recvBufPos = remaining;
}
void Client::reconnect()
{
if (!m_listener) {
@ -689,7 +817,7 @@ void Client::reconnect()
void Client::setState(SocketState state)
{
LOG_DEBUG("[%s] state: %d", m_pool.url(), state);
LOG_DEBUG("[%s] state: \"%s\"", m_pool.url(), states[state]);
if (m_state == state) {
return;
@ -757,7 +885,7 @@ void Client::onConnect(uv_connect_t *req, int status)
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
delete req;
client->login();
client->handshake();
}
@ -789,30 +917,18 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
client->m_recvBufPos += nread;
char* end;
char* start = client->m_recvBuf.base;
size_t remaining = client->m_recvBufPos;
# ifndef XMRIG_NO_TLS
if (client->isTLS()) {
LOG_DEBUG("[%s] TLS received (%d bytes)", client->m_pool.url(), static_cast<int>(nread));
while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
end++;
size_t len = end - start;
client->parse(start, len);
remaining -= len;
start = end;
}
if (remaining == 0) {
client->m_tls->read(client->m_recvBuf.base, client->m_recvBufPos);
client->m_recvBufPos = 0;
return;
}
if (start == client->m_recvBuf.base) {
return;
else
# endif
{
client->read();
}
memcpy(client->m_recvBuf.base, start, remaining);
client->m_recvBufPos = remaining;
}

View file

@ -21,8 +21,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __CLIENT_H__
#define __CLIENT_H__
#ifndef XMRIG_CLIENT_H
#define XMRIG_CLIENT_H
#include <map>
@ -43,6 +43,9 @@ class IClientListener;
class JobResult;
typedef struct bio_st BIO;
class Client
{
public:
@ -54,12 +57,19 @@ public:
ClosingState
};
constexpr static int kResponseTimeout = 20 * 1000;
constexpr static int kResponseTimeout = 20 * 1000;
# ifndef XMRIG_NO_TLS
constexpr static int kInputBufferSize = 1024 * 16;
# else
constexpr static int kInputBufferSize = 1024 * 2;
# endif
Client(int id, const char *agent, IClientListener *listener);
~Client();
bool disconnect();
bool isTLS() const;
int64_t submit(const JobResult &result);
void connect();
void connect(const Pool &pool);
@ -80,6 +90,9 @@ public:
inline void setRetryPause(int ms) { m_retryPause = ms; }
private:
class Tls;
enum Extensions {
NicehashExt = 1,
AlgoExt = 2
@ -89,12 +102,14 @@ private:
bool isCriticalError(const char *message);
bool parseJob(const rapidjson::Value &params, int *code);
bool parseLogin(const rapidjson::Value &result, int *code);
bool send(BIO *bio);
bool verifyAlgorithm(const xmrig::Algorithm &algorithm) const;
int resolve(const char *host);
int64_t send(const rapidjson::Document &doc);
int64_t send(size_t size);
void connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6);
void connect(sockaddr *addr);
void handshake();
void login();
void onClose();
void parse(char *line, size_t len);
@ -102,6 +117,7 @@ private:
void parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error);
void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
void ping();
void read();
void reconnect();
void setState(SocketState state);
void startTimeout();
@ -120,9 +136,9 @@ private:
bool m_ipv6;
bool m_nicehash;
bool m_quiet;
char m_buf[2048];
char m_buf[kInputBufferSize];
char m_ip[46];
char m_sendBuf[768];
char m_sendBuf[1024];
const char *m_agent;
IClientListener *m_listener;
int m_extensions;
@ -135,6 +151,7 @@ private:
size_t m_recvBufPos;
SocketState m_state;
std::map<int64_t, SubmitResult> m_results;
Tls *m_tls;
uint64_t m_expire;
uint64_t m_jobs;
uint64_t m_keepAlive;
@ -150,4 +167,4 @@ private:
};
#endif /* __CLIENT_H__ */
#endif /* XMRIG_CLIENT_H */

View file

@ -46,6 +46,7 @@
Pool::Pool() :
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
{
@ -65,6 +66,7 @@ Pool::Pool() :
*/
Pool::Pool(const char *url) :
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
{
@ -72,8 +74,9 @@ Pool::Pool(const char *url) :
}
Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash) :
Pool::Pool(const char *host, uint16_t port, const char *user, const char *password, int keepAlive, bool nicehash, bool tls) :
m_nicehash(nicehash),
m_tls(tls),
m_keepAlive(keepAlive),
m_port(port),
m_host(host),
@ -134,7 +137,13 @@ bool Pool::parse(const char *url)
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
if (strncasecmp(url, "stratum+tcp://", 14) == 0) {
m_tls = false;
}
else if (strncasecmp(url, "stratum+ssl://", 14) == 0) {
m_tls = true;
}
else {
return false;
}
@ -221,6 +230,9 @@ rapidjson::Value Pool::toJSON(rapidjson::Document &doc) const
break;
}
obj.AddMember("tls", isTLS(), allocator);
obj.AddMember("tls-fingerprint", fingerprint() ? Value(StringRef(fingerprint())).Move() : Value(kNullType).Move(), allocator);
return obj;
}

View file

@ -45,30 +45,35 @@ public:
Pool();
Pool(const char *url);
Pool(const char *host,
uint16_t port,
const char *user = nullptr,
const char *password = nullptr,
int keepAlive = 0,
bool nicehash = false
uint16_t port,
const char *user = nullptr,
const char *password = nullptr,
int keepAlive = 0,
bool nicehash = false,
bool tls = false
);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const char *host() const { return m_host.data(); }
inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; }
inline const char *rigId() const { return m_rigId.data(); }
inline const char *url() const { return m_url.data(); }
inline const char *user() const { return !m_user.isNull() ? m_user.data() : kDefaultUser; }
inline const xmrig::Algorithm &algorithm() const { return m_algorithm; }
inline const xmrig::Algorithms &algorithms() const { return m_algorithms; }
inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setPassword(const char *password) { m_password = password; }
inline void setRigId(const char *rigId) { m_rigId = rigId; }
inline void setUser(const char *user) { m_user = user; }
inline xmrig::Algorithm &algorithm() { return m_algorithm; }
inline bool isNicehash() const { return m_nicehash; }
inline bool isTLS() const { return m_tls; }
inline bool isValid() const { return !m_host.isNull() && m_port > 0; }
inline const char *fingerprint() const { return m_fingerprint.data(); }
inline const char *host() const { return m_host.data(); }
inline const char *password() const { return !m_password.isNull() ? m_password.data() : kDefaultPassword; }
inline const char *rigId() const { return m_rigId.data(); }
inline const char *url() const { return m_url.data(); }
inline const char *user() const { return !m_user.isNull() ? m_user.data() : kDefaultUser; }
inline const xmrig::Algorithm &algorithm() const { return m_algorithm; }
inline const xmrig::Algorithms &algorithms() const { return m_algorithms; }
inline int keepAlive() const { return m_keepAlive; }
inline uint16_t port() const { return m_port; }
inline void setFingerprint(const char *fingerprint) { m_fingerprint = fingerprint; }
inline void setKeepAlive(int keepAlive) { m_keepAlive = keepAlive >= 0 ? keepAlive : 0; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setPassword(const char *password) { m_password = password; }
inline void setRigId(const char *rigId) { m_rigId = rigId; }
inline void setTLS(bool tls) { m_tls = tls; }
inline void setUser(const char *user) { m_user = user; }
inline xmrig::Algorithm &algorithm() { return m_algorithm; }
inline bool operator!=(const Pool &other) const { return !isEqual(other); }
inline bool operator==(const Pool &other) const { return isEqual(other); }
@ -92,10 +97,12 @@ private:
void rebuild();
bool m_nicehash;
bool m_tls;
int m_keepAlive;
uint16_t m_port;
xmrig::Algorithm m_algorithm;
xmrig::Algorithms m_algorithms;
xmrig::c_str m_fingerprint;
xmrig::c_str m_host;
xmrig::c_str m_password;
xmrig::c_str m_rigId;

136
src/common/net/Tls.cpp Normal file
View file

@ -0,0 +1,136 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright 2018 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
#include "common/net/Client.h"
#include "common/net/Tls.h"
#include "common/log/Log.h"
Client::Tls::Tls(Client *client) :
m_buf(),
m_client(client),
m_ssl(nullptr)
{
m_ctx = SSL_CTX_new(SSLv23_method());
assert(m_ctx != nullptr);
if (!m_ctx) {
return;
}
m_writeBio = BIO_new(BIO_s_mem());
m_readBio = BIO_new(BIO_s_mem());
SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
}
Client::Tls::~Tls()
{
if (m_ctx) {
SSL_CTX_free(m_ctx);
}
if (m_ssl) {
SSL_free(m_ssl);
}
}
bool Client::Tls::handshake()
{
m_ssl = SSL_new(m_ctx);
assert(m_ssl != nullptr);
if (!m_ssl) {
return false;
}
SSL_set_connect_state(m_ssl);
SSL_set_bio(m_ssl, m_readBio, m_writeBio);
SSL_do_handshake(m_ssl);
return send();
}
bool Client::Tls::send(const char *data, size_t size)
{
SSL_write(m_ssl, data, size);
return send();
}
void Client::Tls::read(const char *data, size_t size)
{
BIO_write(m_readBio, data, size);
if (!SSL_is_init_finished(m_ssl)) {
const int rc = SSL_connect(m_ssl);
if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) {
send();
}
if (rc == 1) {
if (!verify()) {
LOG_ERR("[%s] TLS certificate verification failed", m_client->m_pool.url());
m_client->close();
return;
}
m_client->login();
}
return;
}
int bytes_read = 0;
while ((bytes_read = SSL_read(m_ssl, m_buf, sizeof(m_buf))) > 0) {
m_client->parse(m_buf, bytes_read);
}
}
bool Client::Tls::send()
{
return m_client->send(m_writeBio);
}
bool Client::Tls::verify()
{
X509* cert = SSL_get_peer_certificate(m_ssl);
if (cert == nullptr) {
return false;
}
return true;
}

58
src/common/net/Tls.h Normal file
View file

@ -0,0 +1,58 @@
/* XMRig
* Copyright 2010 Jeff Garzik <jgarzik@pobox.com>
* Copyright 2012-2014 pooler <pooler@litecoinpool.org>
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2017-2018 XMR-Stak <https://github.com/fireice-uk>, <https://github.com/psychocrypt>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_TLS_H
#define XMRIG_TLS_H
#include <openssl/ssl.h>
#include "common/net/Client.h"
class Client::Tls
{
public:
Tls(Client *client);
~Tls();
bool handshake();
bool send(const char *data, size_t size);
void read(const char *data, size_t size);
private:
bool send();
bool verify();
BIO *m_readBio;
BIO *m_writeBio;
char m_buf[1024 * 2];
Client *m_client;
SSL *m_ssl;
SSL_CTX *m_ctx;
};
#endif /* XMRIG_TLS_H */

View file

@ -132,6 +132,8 @@ static struct option const options[] = {
{ "user-agent", 1, nullptr, xmrig::IConfig::UserAgentKey },
{ "userpass", 1, nullptr, xmrig::IConfig::UserpassKey },
{ "rig-id", 1, nullptr, xmrig::IConfig::RigIdKey },
{ "tls", 0, nullptr, xmrig::IConfig::TlsKey },
{ "tls-fingerprint", 1, nullptr, xmrig::IConfig::FingerprintKey },
{ "version", 0, nullptr, xmrig::IConfig::VersionKey },
{ nullptr, 0, nullptr, 0 }
};
@ -162,15 +164,17 @@ static struct option const config_options[] = {
static struct option const pool_options[] = {
{ "url", 1, nullptr, xmrig::IConfig::UrlKey },
{ "pass", 1, nullptr, xmrig::IConfig::PasswordKey },
{ "user", 1, nullptr, xmrig::IConfig::UserKey },
{ "userpass", 1, nullptr, xmrig::IConfig::UserpassKey },
{ "nicehash", 0, nullptr, xmrig::IConfig::NicehashKey },
{ "keepalive", 2, nullptr, xmrig::IConfig::KeepAliveKey },
{ "variant", 1, nullptr, xmrig::IConfig::VariantKey },
{ "rig-id", 1, nullptr, xmrig::IConfig::RigIdKey },
{ nullptr, 0, nullptr, 0 }
{ "url", 1, nullptr, xmrig::IConfig::UrlKey },
{ "pass", 1, nullptr, xmrig::IConfig::PasswordKey },
{ "user", 1, nullptr, xmrig::IConfig::UserKey },
{ "userpass", 1, nullptr, xmrig::IConfig::UserpassKey },
{ "nicehash", 0, nullptr, xmrig::IConfig::NicehashKey },
{ "keepalive", 2, nullptr, xmrig::IConfig::KeepAliveKey },
{ "variant", 1, nullptr, xmrig::IConfig::VariantKey },
{ "rig-id", 1, nullptr, xmrig::IConfig::RigIdKey },
{ "tls", 0, nullptr, xmrig::IConfig::TlsKey },
{ "tls-fingerprint", 1, nullptr, xmrig::IConfig::FingerprintKey },
{ nullptr, 0, nullptr, 0 }
};