Merge branch 'feature-tls' into dev

This commit is contained in:
XMRig 2018-09-18 04:13:40 +03:00
commit dc76879188
20 changed files with 751 additions and 191 deletions

View file

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

22
cmake/OpenSSL.cmake Normal file
View file

@ -0,0 +1,22 @@
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()
if (WIN32)
set(EXTRA_LIBS ${EXTRA_LIBS} Crypt32)
endif()
else()
set(TLS_SOURCES "")
set(OPENSSL_LIBRARIES "")
add_definitions(/DXMRIG_NO_TLS)
endif()

View file

@ -37,24 +37,6 @@
#include "version.h" #include "version.h"
static void print_versions(xmrig::Config *config)
{
char buf[16] = { 0 };
# if defined(__clang__)
snprintf(buf, 16, " clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
# elif defined(__GNUC__)
snprintf(buf, 16, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif defined(_MSC_VER)
snprintf(buf, 16, " MSVC/%d", MSVC_VERSION);
# endif
Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" libuv/%s%s")
: " * %-13s%s/%s libuv/%s%s",
"VERSIONS", APP_NAME, APP_VERSION, uv_version_string(), buf);
}
static void print_memory(xmrig::Config *config) { static void print_memory(xmrig::Config *config) {
# ifdef _WIN32 # ifdef _WIN32
if (config->isColors()) { if (config->isColors()) {
@ -71,18 +53,18 @@ static void print_memory(xmrig::Config *config) {
static void print_cpu(xmrig::Config *config) static void print_cpu(xmrig::Config *config)
{ {
if (config->isColors()) { if (config->isColors()) {
Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%s (%d) %sx64 %sAES-NI", Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%s (%d)") " %sx64 %sAES",
"CPU", "CPU",
Cpu::brand(), Cpu::brand(),
Cpu::sockets(), Cpu::sockets(),
Cpu::isX64() ? "\x1B[1;32m" : "\x1B[1;31m-", Cpu::isX64() ? "\x1B[1;32m" : "\x1B[1;31m-",
Cpu::hasAES() ? "\x1B[1;32m" : "\x1B[1;31m-"); Cpu::hasAES() ? "\x1B[1;32m" : "\x1B[1;31m-");
# ifndef XMRIG_NO_LIBCPUID # ifndef XMRIG_NO_LIBCPUID
Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s") "%.1f MB/%.1f MB", "CPU L2/L3", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("%-13s%.1f MB/%.1f MB"), "CPU L2/L3", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif # endif
} }
else { else {
Log::i()->text(" * %-13s%s (%d) %sx64 %sAES-NI", "CPU", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-"); Log::i()->text(" * %-13s%s (%d) %sx64 %sAES", "CPU", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
# ifndef XMRIG_NO_LIBCPUID # ifndef XMRIG_NO_LIBCPUID
Log::i()->text(" * %-13s%.1f MB/%.1f MB", "CPU L2/L3", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0); Log::i()->text(" * %-13s%.1f MB/%.1f MB", "CPU L2/L3", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif # endif
@ -120,44 +102,6 @@ static void print_threads(xmrig::Config *config)
} }
static void print_pools(xmrig::Config *config)
{
const std::vector<Pool> &pools = config->pools();
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") CYAN_BOLD("%s") " variant " WHITE_BOLD("%s")
: " * POOL #%-7d%s variant %s",
i + 1,
pools[i].url(),
pools[i].algorithm().variantName()
);
}
# ifdef APP_DEBUG
LOG_NOTICE("POOLS --------------------------------------------------------------------");
for (const Pool &pool : pools) {
pool.print();
}
LOG_NOTICE("--------------------------------------------------------------------------");
# endif
}
#ifndef XMRIG_NO_API
static void print_api(xmrig::Config *config)
{
const int port = config->apiPort();
if (port == 0) {
return;
}
Log::i()->text(config->isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d")
: " * %-13s%s:%d",
"API BIND", config->isApiIPv6() ? "[::]" : "0.0.0.0", port);
}
#endif
static void print_commands(xmrig::Config *config) static void print_commands(xmrig::Config *config)
{ {
if (config->isColors()) { if (config->isColors()) {
@ -173,15 +117,12 @@ static void print_commands(xmrig::Config *config)
void Summary::print(xmrig::Controller *controller) void Summary::print(xmrig::Controller *controller)
{ {
print_versions(controller->config()); controller->config()->printVersions();
print_memory(controller->config()); print_memory(controller->config());
print_cpu(controller->config()); print_cpu(controller->config());
print_threads(controller->config()); print_threads(controller->config());
print_pools(controller->config()); controller->config()->printPools();
controller->config()->printAPI();
# ifndef XMRIG_NO_API
print_api(controller->config());
# endif
print_commands(controller->config()); print_commands(controller->config());
} }

View file

@ -26,6 +26,12 @@
#include <uv.h> #include <uv.h>
#ifndef XMRIG_NO_TLS
# include <openssl/ssl.h>
# include <openssl/err.h>
#endif
#include "Platform.h" #include "Platform.h"
@ -61,3 +67,23 @@ const char *Platform::defaultConfigName()
*m_defaultConfigName = '\0'; *m_defaultConfigName = '\0';
return nullptr; 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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __PLATFORM_H__ #ifndef XMRIG_PLATFORM_H
#define __PLATFORM_H__ #define XMRIG_PLATFORM_H
#include <stdint.h> #include <stdint.h>
@ -43,9 +43,11 @@ public:
static inline const char *userAgent() { return m_userAgent.data(); } static inline const char *userAgent() { return m_userAgent.data(); }
private: private:
static char *createUserAgent();
static char m_defaultConfigName[520]; static char m_defaultConfigName[520];
static xmrig::c_str m_userAgent; static xmrig::c_str m_userAgent;
}; };
#endif /* __PLATFORM_H__ */ #endif /* XMRIG_PLATFORM_H */

View file

@ -38,7 +38,7 @@
#endif #endif
static inline char *createUserAgent() char *Platform::createUserAgent()
{ {
const size_t max = 160; 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) void Platform::setProcessPriority(int priority)
{ {

View file

@ -52,7 +52,7 @@ typedef cpuset_t cpu_set_t;
#endif #endif
static inline char *createUserAgent() char *Platform::createUserAgent()
{ {
const size_t max = 160; 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::setProcessPriority(int priority)
{ {
} }
void Platform::setThreadPriority(int priority) void Platform::setThreadPriority(int priority)
{ {
if (priority == -1) { 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 auto osver = winOsVersion();
const size_t max = 160; 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) void Platform::setProcessPriority(int priority)
{ {
if (priority == -1) { if (priority == -1) {

View file

@ -29,12 +29,37 @@
#include <uv.h> #include <uv.h>
#ifndef XMRIG_NO_HTTPD
# include <microhttpd.h>
#endif
#ifndef XMRIG_NO_TLS
# include <openssl/opensslv.h>
#endif
#ifdef XMRIG_AMD_PROJECT
# if defined(__APPLE__)
# include <OpenCL/cl.h>
# else
# include "3rdparty/CL/cl.h"
# endif
#endif
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#endif
#include "common/config/CommonConfig.h" #include "common/config/CommonConfig.h"
#include "common/log/Log.h" #include "common/log/Log.h"
#include "donate.h" #include "donate.h"
#include "rapidjson/document.h" #include "rapidjson/document.h"
#include "rapidjson/filewritestream.h" #include "rapidjson/filewritestream.h"
#include "rapidjson/prettywriter.h" #include "rapidjson/prettywriter.h"
#include "version.h"
xmrig::CommonConfig::CommonConfig() : xmrig::CommonConfig::CommonConfig() :
@ -69,8 +94,102 @@ xmrig::CommonConfig::CommonConfig() :
} }
xmrig::CommonConfig::~CommonConfig() void xmrig::CommonConfig::printAPI()
{ {
# ifndef XMRIG_NO_API
if (apiPort() == 0) {
return;
}
Log::i()->text(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN("%s:") CYAN_BOLD("%d")
: " * %-13s%s:%d",
"API BIND", isApiIPv6() ? "[::]" : "0.0.0.0", apiPort());
# endif
}
void xmrig::CommonConfig::printPools()
{
for (size_t i = 0; i < m_activePools.size(); ++i) {
if (!isColors()) {
Log::i()->text(" * POOL #%-7zu%s variant=%s, TLS=%d",
i + 1,
m_activePools[i].url(),
m_activePools[i].algorithm().variantName(),
static_cast<int>(m_activePools[i].isTLS())
);
}
else {
Log::i()->text(GREEN_BOLD(" * ") WHITE_BOLD("POOL #%-7zu") "\x1B[1;%dm%s\x1B[0m variant " WHITE_BOLD("%s"),
i + 1,
m_activePools[i].isTLS() ? 32 : 36,
m_activePools[i].url(),
m_activePools[i].algorithm().variantName()
);
}
}
# ifdef APP_DEBUG
LOG_NOTICE("POOLS --------------------------------------------------------------------");
for (const Pool &pool : m_activePools) {
pool.print();
}
LOG_NOTICE("--------------------------------------------------------------------------");
# endif
}
void xmrig::CommonConfig::printVersions()
{
char buf[256] = { 0 };
# if defined(__clang__)
snprintf(buf, sizeof buf, "clang/%d.%d.%d", __clang_major__, __clang_minor__, __clang_patchlevel__);
# elif defined(__GNUC__)
snprintf(buf, sizeof buf, "gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif defined(_MSC_VER)
snprintf(buf, sizeof buf, "MSVC/%d", MSVC_VERSION);
# endif
Log::i()->text(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13s") CYAN_BOLD("%s/%s") WHITE_BOLD(" %s")
: " * %-13s%s/%s %s",
"ABOUT", APP_NAME, APP_VERSION, buf);
# if defined(XMRIG_AMD_PROJECT)
# if CL_VERSION_2_0
const char *ocl = "2.0";
# elif CL_VERSION_1_2
const char *ocl = "1.2";
# elif CL_VERSION_1_1
const char *ocl = "1.1";
# elif CL_VERSION_1_0
const char *ocl = "1.0";
# else
const char *ocl = "0.0";
# endif
int length = snprintf(buf, sizeof buf, "OpenCL/%s ", ocl);
# elif defined(XMRIG_NVIDIA_PROJECT)
const int cudaVersion = cuda_get_runtime_version();
int length = snprintf(buf, sizeof buf, "CUDA/%d.%d ", cudaVersion / 1000, cudaVersion % 100);
# else
memset(buf, 0, 16);
int length = 0;
# endif
# if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT)
{
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
length += snprintf(buf + length, (sizeof buf) - length, "OpenSSL/%.*s ", static_cast<int>(strchr(v, ' ') - v), v);
}
# endif
# ifndef XMRIG_NO_HTTPD
length += snprintf(buf + length, (sizeof buf) - length, "microhttpd/%s ", MHD_get_version());
# endif
Log::i()->text(isColors() ? GREEN_BOLD(" * ") WHITE_BOLD("%-13slibuv/%s %s")
: " * %-13slibuv/%s %s",
"LIBS", uv_version_string(), buf);
} }
@ -126,6 +245,12 @@ bool xmrig::CommonConfig::finalize()
pool.adjust(m_algorithm); pool.adjust(m_algorithm);
if (pool.isValid() && pool.algorithm().isValid()) { if (pool.isValid() && pool.algorithm().isValid()) {
# ifdef XMRIG_NO_TLS
if (pool.isTLS()) {
continue;
}
# endif
m_activePools.push_back(std::move(pool)); m_activePools.push_back(std::move(pool));
} }
} }
@ -157,6 +282,10 @@ bool xmrig::CommonConfig::parseBoolean(int key, bool enable)
m_pools.back().setKeepAlive(enable ? Pool::kKeepAliveTimeout : 0); m_pools.back().setKeepAlive(enable ? Pool::kKeepAliveTimeout : 0);
break; break;
case TlsKey: /* --tls */
m_pools.back().setTLS(enable);
break;
# ifndef XMRIG_PROXY_PROJECT # ifndef XMRIG_PROXY_PROJECT
case NicehashKey: /* --nicehash */ case NicehashKey: /* --nicehash */
m_pools.back().setNicehash(enable); m_pools.back().setNicehash(enable);
@ -235,6 +364,10 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
m_pools.back().setRigId(arg); m_pools.back().setRigId(arg);
break; break;
case FingerprintKey: /* --tls-fingerprint */
m_pools.back().setFingerprint(arg);
break;
case VariantKey: /* --variant */ case VariantKey: /* --variant */
m_pools.back().algorithm().parseVariant(arg); m_pools.back().algorithm().parseVariant(arg);
break; break;
@ -269,6 +402,7 @@ bool xmrig::CommonConfig::parseString(int key, const char *arg)
case SyslogKey: /* --syslog */ case SyslogKey: /* --syslog */
case KeepAliveKey: /* --keepalive */ case KeepAliveKey: /* --keepalive */
case NicehashKey: /* --nicehash */ case NicehashKey: /* --nicehash */
case TlsKey: /* --tls */
case ApiIPv6Key: /* --api-ipv6 */ case ApiIPv6Key: /* --api-ipv6 */
case DryRunKey: /* --dry-run */ case DryRunKey: /* --dry-run */
return parseBoolean(key, true); return parseBoolean(key, true);

View file

@ -21,8 +21,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __COMMONCONFIG_H__ #ifndef XMRIG_COMMONCONFIG_H
#define __COMMONCONFIG_H__ #define XMRIG_COMMONCONFIG_H
#include <vector> #include <vector>
@ -41,7 +41,6 @@ class CommonConfig : public IConfig
{ {
public: public:
CommonConfig(); CommonConfig();
~CommonConfig();
inline bool isApiIPv6() const { return m_apiIPv6; } inline bool isApiIPv6() const { return m_apiIPv6; }
inline bool isApiRestricted() const { return m_apiRestricted; } inline bool isApiRestricted() const { return m_apiRestricted; }
@ -68,6 +67,10 @@ public:
bool save() override; bool save() override;
void printAPI();
void printPools();
void printVersions();
protected: protected:
enum State { enum State {
NoneState, NoneState,

View file

@ -32,6 +32,11 @@
#endif #endif
#ifndef XMRIG_NO_TLS
# include <openssl/opensslv.h>
#endif
#include "common/config/ConfigLoader.h" #include "common/config/ConfigLoader.h"
#include "common/config/ConfigWatcher.h" #include "common/config/ConfigWatcher.h"
#include "common/interfaces/IConfig.h" #include "common/interfaces/IConfig.h"
@ -313,6 +318,13 @@ void xmrig::ConfigLoader::showVersion()
printf("\nlibuv/%s\n", uv_version_string()); printf("\nlibuv/%s\n", uv_version_string());
# ifndef XMRIG_NO_HTTPD # ifndef XMRIG_NO_HTTPD
printf("libmicrohttpd/%s\n", MHD_get_version()); printf("microhttpd/%s\n", MHD_get_version());
# endif
# if !defined(XMRIG_NO_TLS) && defined(OPENSSL_VERSION_TEXT)
{
constexpr const char *v = OPENSSL_VERSION_TEXT + 8;
printf("OpenSSL/%.*s\n", static_cast<int>(strchr(v, ' ') - v), v);
}
# endif # endif
} }

View file

@ -63,6 +63,8 @@ public:
VerboseKey = 1100, VerboseKey = 1100,
VersionKey = 'V', VersionKey = 'V',
WatchKey = 1105, WatchKey = 1105,
TlsKey = 1013,
FingerprintKey = 1014,
// xmrig common // xmrig common
CPUPriorityKey = 1021, CPUPriorityKey = 1021,

View file

@ -29,6 +29,13 @@
#include <utility> #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/interfaces/IClientListener.h"
#include "common/log/Log.h" #include "common/log/Log.h"
#include "common/net/Client.h" #include "common/net/Client.h"
@ -48,6 +55,17 @@ int64_t Client::m_sequence = 1;
xmrig::Storage<Client> Client::m_storage; 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) : Client::Client(int id, const char *agent, IClientListener *listener) :
m_ipv6(false), m_ipv6(false),
m_nicehash(false), m_nicehash(false),
@ -61,6 +79,7 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_failures(0), m_failures(0),
m_recvBufPos(0), m_recvBufPos(0),
m_state(UnconnectedState), m_state(UnconnectedState),
m_tls(nullptr),
m_expire(0), m_expire(0),
m_jobs(0), m_jobs(0),
m_keepAlive(0), m_keepAlive(0),
@ -92,6 +111,12 @@ Client::~Client()
void Client::connect() void Client::connect()
{ {
# ifndef XMRIG_NO_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host()); resolve(m_pool.host());
} }
@ -122,6 +147,7 @@ void Client::deleteLater()
} }
void Client::setPool(const Pool &pool) void Client::setPool(const Pool &pool)
{ {
if (!pool.isValid()) { if (!pool.isValid()) {
@ -160,6 +186,30 @@ 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->version();
}
# endif
return nullptr;
}
int64_t Client::submit(const JobResult &result) int64_t Client::submit(const JobResult &result)
{ {
using namespace rapidjson; using namespace rapidjson;
@ -245,6 +295,16 @@ bool Client::isCriticalError(const char *message)
} }
bool Client::isTLS() const
{
# ifndef XMRIG_NO_TLS
return m_pool.isTLS() && m_tls;
# else
return false;
# endif
}
bool Client::parseJob(const rapidjson::Value &params, int *code) bool Client::parseJob(const rapidjson::Value &params, int *code)
{ {
if (!params.IsObject()) { if (!params.IsObject()) {
@ -330,6 +390,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);
}
(void) BIO_reset(bio);
return result;
# else
return false;
# endif
}
bool Client::verifyAlgorithm(const xmrig::Algorithm &algorithm) const bool Client::verifyAlgorithm(const xmrig::Algorithm &algorithm) const
{ {
# ifdef XMRIG_PROXY_PROJECT # ifdef XMRIG_PROXY_PROJECT
@ -404,16 +497,27 @@ int64_t Client::send(const rapidjson::Document &doc)
int64_t Client::send(size_t size) int64_t Client::send(size_t size)
{ {
LOG_DEBUG("[%s] send (%d bytes): \"%s\"", m_pool.url(), size, m_sendBuf); 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); # ifndef XMRIG_NO_TLS
return -1; 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) { if (uv_try_write(m_stream, &buf, 1) < 0) {
close(); close();
return -1; return -1;
}
} }
m_expire = uv_now(uv_default_loop()) + kResponseTimeout; m_expire = uv_now(uv_default_loop()) + kResponseTimeout;
@ -463,6 +567,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() void Client::login()
{ {
using namespace rapidjson; using namespace rapidjson;
@ -511,6 +631,13 @@ void Client::onClose()
m_socket = nullptr; m_socket = nullptr;
setState(UnconnectedState); setState(UnconnectedState);
# ifndef XMRIG_NO_TLS
if (m_tls) {
delete m_tls;
m_tls = nullptr;
}
# endif
reconnect(); reconnect();
} }
@ -665,6 +792,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() void Client::reconnect()
{ {
if (!m_listener) { if (!m_listener) {
@ -689,7 +845,7 @@ void Client::reconnect()
void Client::setState(SocketState state) 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) { if (m_state == state) {
return; return;
@ -757,7 +913,7 @@ void Client::onConnect(uv_connect_t *req, int status)
uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead); uv_read_start(client->m_stream, Client::onAllocBuffer, Client::onRead);
delete req; delete req;
client->login(); client->handshake();
} }
@ -789,30 +945,18 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
client->m_recvBufPos += nread; client->m_recvBufPos += nread;
char* end; # ifndef XMRIG_NO_TLS
char* start = client->m_recvBuf.base; if (client->isTLS()) {
size_t remaining = client->m_recvBufPos; 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) { client->m_tls->read(client->m_recvBuf.base, client->m_recvBufPos);
end++;
size_t len = end - start;
client->parse(start, len);
remaining -= len;
start = end;
}
if (remaining == 0) {
client->m_recvBufPos = 0; client->m_recvBufPos = 0;
return;
} }
else
if (start == client->m_recvBuf.base) { # endif
return; {
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/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef __CLIENT_H__ #ifndef XMRIG_CLIENT_H
#define __CLIENT_H__ #define XMRIG_CLIENT_H
#include <map> #include <map>
@ -43,6 +43,9 @@ class IClientListener;
class JobResult; class JobResult;
typedef struct bio_st BIO;
class Client class Client
{ {
public: public:
@ -54,12 +57,20 @@ public:
ClosingState 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(int id, const char *agent, IClientListener *listener);
~Client(); ~Client();
bool disconnect(); bool disconnect();
const char *tlsFingerprint() const;
const char *tlsVersion() const;
int64_t submit(const JobResult &result); int64_t submit(const JobResult &result);
void connect(); void connect();
void connect(const Pool &pool); void connect(const Pool &pool);
@ -80,6 +91,9 @@ public:
inline void setRetryPause(int ms) { m_retryPause = ms; } inline void setRetryPause(int ms) { m_retryPause = ms; }
private: private:
class Tls;
enum Extensions { enum Extensions {
NicehashExt = 1, NicehashExt = 1,
AlgoExt = 2 AlgoExt = 2
@ -87,14 +101,17 @@ private:
bool close(); bool close();
bool isCriticalError(const char *message); bool isCriticalError(const char *message);
bool isTLS() const;
bool parseJob(const rapidjson::Value &params, int *code); bool parseJob(const rapidjson::Value &params, int *code);
bool parseLogin(const rapidjson::Value &result, int *code); bool parseLogin(const rapidjson::Value &result, int *code);
bool send(BIO *bio);
bool verifyAlgorithm(const xmrig::Algorithm &algorithm) const; bool verifyAlgorithm(const xmrig::Algorithm &algorithm) const;
int resolve(const char *host); int resolve(const char *host);
int64_t send(const rapidjson::Document &doc); int64_t send(const rapidjson::Document &doc);
int64_t send(size_t size); int64_t send(size_t size);
void connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6); void connect(const std::vector<addrinfo*> &ipv4, const std::vector<addrinfo*> &ipv6);
void connect(sockaddr *addr); void connect(sockaddr *addr);
void handshake();
void login(); void login();
void onClose(); void onClose();
void parse(char *line, size_t len); void parse(char *line, size_t len);
@ -102,6 +119,7 @@ private:
void parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error); 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 parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
void ping(); void ping();
void read();
void reconnect(); void reconnect();
void setState(SocketState state); void setState(SocketState state);
void startTimeout(); void startTimeout();
@ -120,9 +138,9 @@ private:
bool m_ipv6; bool m_ipv6;
bool m_nicehash; bool m_nicehash;
bool m_quiet; bool m_quiet;
char m_buf[2048]; char m_buf[kInputBufferSize];
char m_ip[46]; char m_ip[46];
char m_sendBuf[768]; char m_sendBuf[1024];
const char *m_agent; const char *m_agent;
IClientListener *m_listener; IClientListener *m_listener;
int m_extensions; int m_extensions;
@ -135,6 +153,7 @@ private:
size_t m_recvBufPos; size_t m_recvBufPos;
SocketState m_state; SocketState m_state;
std::map<int64_t, SubmitResult> m_results; std::map<int64_t, SubmitResult> m_results;
Tls *m_tls;
uint64_t m_expire; uint64_t m_expire;
uint64_t m_jobs; uint64_t m_jobs;
uint64_t m_keepAlive; uint64_t m_keepAlive;
@ -150,4 +169,4 @@ private:
}; };
#endif /* __CLIENT_H__ */ #endif /* XMRIG_CLIENT_H */

View file

@ -46,6 +46,7 @@
Pool::Pool() : Pool::Pool() :
m_nicehash(false), m_nicehash(false),
m_tls(false),
m_keepAlive(0), m_keepAlive(0),
m_port(kDefaultPort) m_port(kDefaultPort)
{ {
@ -65,6 +66,7 @@ Pool::Pool() :
*/ */
Pool::Pool(const char *url) : Pool::Pool(const char *url) :
m_nicehash(false), m_nicehash(false),
m_tls(false),
m_keepAlive(0), m_keepAlive(0),
m_port(kDefaultPort) 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_nicehash(nicehash),
m_tls(tls),
m_keepAlive(keepAlive), m_keepAlive(keepAlive),
m_port(port), m_port(port),
m_host(host), m_host(host),
@ -114,15 +117,17 @@ bool Pool::isCompatible(const xmrig::Algorithm &algorithm) const
bool Pool::isEqual(const Pool &other) const bool Pool::isEqual(const Pool &other) const
{ {
return (m_nicehash == other.m_nicehash return (m_nicehash == other.m_nicehash
&& m_keepAlive == other.m_keepAlive && m_tls == other.m_tls
&& m_port == other.m_port && m_keepAlive == other.m_keepAlive
&& m_algorithm == other.m_algorithm && m_port == other.m_port
&& m_host == other.m_host && m_algorithm == other.m_algorithm
&& m_password == other.m_password && m_fingerprint == other.m_fingerprint
&& m_rigId == other.m_rigId && m_host == other.m_host
&& m_url == other.m_url && m_password == other.m_password
&& m_user == other.m_user); && m_rigId == other.m_rigId
&& m_url == other.m_url
&& m_user == other.m_user);
} }
@ -134,7 +139,13 @@ bool Pool::parse(const char *url)
const char *base = url; const char *base = url;
if (p) { 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; return false;
} }
@ -221,6 +232,9 @@ rapidjson::Value Pool::toJSON(rapidjson::Document &doc) const
break; break;
} }
obj.AddMember("tls", isTLS(), allocator);
obj.AddMember("tls-fingerprint", fingerprint() ? Value(StringRef(fingerprint())).Move() : Value(kNullType).Move(), allocator);
return obj; return obj;
} }

View file

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

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

@ -0,0 +1,190 @@
/* 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"
#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)
{
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();
}
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;
}
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();
} else if (rc == 1) {
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();
}
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)
{
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;
}

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

@ -0,0 +1,62 @@
/* 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);
const char *fingerprint() const;
const char *version() const;
void read(const char *data, size_t size);
private:
bool send();
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;
};
#endif /* XMRIG_TLS_H */

View file

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

View file

@ -101,7 +101,15 @@ void Network::onActive(IStrategy *strategy, Client *client)
m_state.setPool(client->host(), client->port(), client->ip()); m_state.setPool(client->host(), client->port(), client->ip());
LOG_INFO(isColors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", 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[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);
}
} }