1
0
mirror of https://github.com/xmrig/xmrig.git synced 2026-02-02 10:03:05 -05:00

Merge from xmrig-2.8.0-rc

This commit is contained in:
MoneroOcean
2018-10-02 07:06:41 +02:00
86 changed files with 4366 additions and 1946 deletions

View File

@@ -30,6 +30,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"
@@ -51,6 +58,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),
@@ -64,6 +82,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),
@@ -95,6 +114,12 @@ Client::~Client()
void Client::connect()
{
# ifndef XMRIG_NO_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host());
}
@@ -125,6 +150,7 @@ void Client::deleteLater()
}
void Client::setPool(const Pool &pool)
{
if (!pool.isValid()) {
@@ -163,6 +189,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)
{
using namespace rapidjson;
@@ -248,6 +298,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)
{
if (!params.IsObject()) {
@@ -276,16 +336,16 @@ bool Client::parseJob(const rapidjson::Value &params, int *code)
const rapidjson::Value &variant = params["variant"];
if (variant.IsInt()) {
job.algorithm().parseVariant(variant.GetInt());
job.setVariant(variant.GetInt());
}
else if (variant.IsString()){
job.algorithm().parseVariant(variant.GetString());
job.setVariant(variant.GetString());
}
}
// moved algo after variant parsing to override variant that is considered to be outdated now
if (params.HasMember("algo")) {
job.algorithm().parseAlgorithm(params["algo"].GetString());
job.setAlgorithm(params["algo"].GetString());
}
if (!verifyAlgorithm(job.algorithm())) {
@@ -337,6 +397,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
{
# ifdef XMRIG_PROXY_PROJECT
@@ -396,7 +489,9 @@ int64_t Client::send(const rapidjson::Document &doc)
doc.Accept(writer);
const size_t size = buffer.GetSize();
if (size > (sizeof(m_buf) - 2)) {
if (size > (sizeof(m_sendBuf) - 2)) {
LOG_ERR("[%s] send failed: \"send buffer overflow: %zu > %zu\"", m_pool.url(), size, (sizeof(m_sendBuf) - 2));
close();
return -1;
}
@@ -411,16 +506,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;
@@ -470,6 +576,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;
@@ -528,6 +650,13 @@ void Client::onClose()
m_socket = nullptr;
setState(UnconnectedState);
# ifndef XMRIG_NO_TLS
if (m_tls) {
delete m_tls;
m_tls = nullptr;
}
# endif
reconnect();
}
@@ -682,6 +811,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) {
@@ -706,7 +864,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;
@@ -774,7 +932,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();
}
@@ -806,30 +964,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

@@ -22,8 +22,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>
@@ -44,6 +44,9 @@ class IClientListener;
class JobResult;
typedef struct bio_st BIO;
class Client
{
public:
@@ -55,12 +58,20 @@ 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();
const char *tlsFingerprint() const;
const char *tlsVersion() const;
int64_t submit(const JobResult &result);
void connect();
void connect(const Pool &pool);
@@ -80,6 +91,9 @@ public:
inline void setRetryPause(int ms) { m_retryPause = ms; }
private:
class Tls;
enum Extensions {
NicehashExt = 1,
AlgoExt = 2
@@ -87,14 +101,17 @@ private:
bool close();
bool isCriticalError(const char *message);
bool isTLS() const;
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 +119,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 +138,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[2048];
const char *m_agent;
IClientListener *m_listener;
int m_extensions;
@@ -135,6 +153,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 +169,4 @@ private:
};
#endif /* __CLIENT_H__ */
#endif /* XMRIG_CLIENT_H */

View File

@@ -6,6 +6,7 @@
* 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>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
@@ -59,6 +60,7 @@ static inline char hf_bin2hex(unsigned char c)
Job::Job() :
m_autoVariant(false),
m_nicehash(false),
m_poolId(-2),
m_threadId(-1),
@@ -70,7 +72,8 @@ Job::Job() :
}
Job::Job(int poolId, bool nicehash, xmrig::Algorithm algorithm, const xmrig::Id &clientId) :
Job::Job(int poolId, bool nicehash, const xmrig::Algorithm &algorithm, const xmrig::Id &clientId) :
m_autoVariant(algorithm.variant() == xmrig::VARIANT_AUTO),
m_nicehash(nicehash),
m_poolId(poolId),
m_threadId(-1),
@@ -113,6 +116,10 @@ bool Job::setBlob(const char *blob)
m_nicehash = true;
}
if (m_autoVariant) {
m_algorithm.setVariant(variant());
}
# ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2);
@@ -170,25 +177,13 @@ bool Job::setTarget(const char *target)
}
xmrig::Variant Job::variant() const
void Job::setAlgorithm(const char *algo)
{
if (m_algorithm.variant() == xmrig::VARIANT_XTL && m_blob[0] < 4) {
return xmrig::VARIANT_1;
}
if (m_algorithm.variant() == xmrig::VARIANT_MSR && m_blob[0] < 7) {
return xmrig::VARIANT_1;
}
if (m_algorithm.variant() == xmrig::VARIANT_XHV && m_blob[0] < 3) {
return xmrig::VARIANT_0;
}
m_algorithm.parseAlgorithm(algo);
if (m_algorithm.variant() == xmrig::VARIANT_AUTO) {
return m_algorithm.algo() == xmrig::CRYPTONIGHT_HEAVY ? xmrig::VARIANT_0 : xmrig::VARIANT_1;
m_algorithm.setVariant(variant());
}
return m_algorithm.variant();
}
@@ -236,3 +231,25 @@ bool Job::operator!=(const Job &other) const
{
return m_id != other.m_id || memcmp(m_blob, other.m_blob, sizeof(m_blob)) != 0;
}
xmrig::Variant Job::variant() const
{
using namespace xmrig;
switch (m_algorithm.algo()) {
case CRYPTONIGHT:
return (m_blob[0] >= 8) ? VARIANT_2 : VARIANT_1;
case CRYPTONIGHT_LITE:
return VARIANT_1;
case CRYPTONIGHT_HEAVY:
return VARIANT_0;
default:
break;
}
return m_algorithm.variant();
}

View File

@@ -6,6 +6,7 @@
* 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>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
@@ -23,8 +24,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __JOB_H__
#define __JOB_H__
#ifndef XMRIG_JOB_H
#define XMRIG_JOB_H
#include <stddef.h>
@@ -39,7 +40,7 @@ class Job
{
public:
Job();
Job(int poolId, bool nicehash, xmrig::Algorithm algorithm, const xmrig::Id &clientId);
Job(int poolId, bool nicehash, const xmrig::Algorithm &algorithm, const xmrig::Id &clientId);
~Job();
bool setBlob(const char *blob);
@@ -47,7 +48,7 @@ public:
bool setTarget(const char *target);
// for algo benchmarking to set PoW variant
void setAlgorithm(const xmrig::Algorithm& algorithm) { m_algorithm = algorithm; }
xmrig::Variant variant() const;
void setAlgorithm(const char *algo);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
@@ -67,7 +68,8 @@ public:
inline void setClientId(const xmrig::Id &id) { m_clientId = id; }
inline void setPoolId(int poolId) { m_poolId = poolId; }
inline void setThreadId(int threadId) { m_threadId = threadId; }
inline xmrig::Algorithm &algorithm() { return m_algorithm; }
inline void setVariant(const char *variant) { m_algorithm.parseVariant(variant); }
inline void setVariant(int variant) { m_algorithm.parseVariant(variant); }
# ifdef XMRIG_PROXY_PROJECT
inline char *rawBlob() { return m_rawBlob; }
@@ -87,6 +89,7 @@ public:
bool operator!=(const Job &other) const;
private:
bool m_autoVariant;
bool m_nicehash;
int m_poolId;
int m_threadId;
@@ -104,4 +107,4 @@ private:
# endif
};
#endif /* __JOB_H__ */
#endif /* XMRIG_JOB_H */

View File

@@ -5,6 +5,7 @@
* 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 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
@@ -46,11 +47,13 @@
Pool::Pool() :
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
{
// here xmrig now resuts all possible supported algorithms
m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_1));
m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_2));
m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_0));
m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_XTL));
m_algorithms.push_back(xmrig::Algorithm(xmrig::CRYPTONIGHT, xmrig::VARIANT_MSR));
@@ -79,6 +82,7 @@ Pool::Pool() :
*/
Pool::Pool(const char *url) :
m_nicehash(false),
m_tls(false),
m_keepAlive(0),
m_port(kDefaultPort)
{
@@ -86,8 +90,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),
@@ -128,15 +133,17 @@ bool Pool::isCompatible(const xmrig::Algorithm &algorithm) const
bool Pool::isEqual(const Pool &other) const
{
return (m_nicehash == other.m_nicehash
&& m_keepAlive == other.m_keepAlive
&& m_port == other.m_port
&& m_algorithm == other.m_algorithm
&& m_host == other.m_host
&& m_password == other.m_password
&& m_rigId == other.m_rigId
&& m_url == other.m_url
&& m_user == other.m_user);
return (m_nicehash == other.m_nicehash
&& m_tls == other.m_tls
&& m_keepAlive == other.m_keepAlive
&& m_port == other.m_port
&& m_algorithm == other.m_algorithm
&& m_fingerprint == other.m_fingerprint
&& m_host == other.m_host
&& m_password == other.m_password
&& m_rigId == other.m_rigId
&& m_url == other.m_url
&& m_user == other.m_user);
}
@@ -148,7 +155,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;
}
@@ -227,6 +240,7 @@ rapidjson::Value Pool::toJSON(rapidjson::Document &doc) const
case xmrig::VARIANT_AUTO:
case xmrig::VARIANT_0:
case xmrig::VARIANT_1:
case xmrig::VARIANT_2:
obj.AddMember("variant", m_algorithm.variant(), allocator);
break;
@@ -235,6 +249,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;
}
@@ -353,7 +370,7 @@ void Pool::adjustVariant(const xmrig::Variant variantHint)
if (m_algorithm.algo() == CRYPTONIGHT_HEAVY) {
m_algorithm.setVariant(VARIANT_0);
}
else {
else if (m_algorithm.algo() == CRYPTONIGHT_LITE) {
m_algorithm.setVariant(VARIANT_1);
}
# endif

View File

@@ -5,6 +5,7 @@
* 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 SChernykh <https://github.com/SChernykh>
* Copyright 2016-2018 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright 2018 MoneroOcean <https://github.com/MoneroOcean>, <support@moneroocean.stream>
*
@@ -22,8 +23,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __POOL_H__
#define __POOL_H__
#ifndef XMRIG_POOL_H
#define XMRIG_POOL_H
#include <vector>
@@ -45,30 +46,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); }
@@ -89,10 +95,12 @@ private:
void adjustVariant(const xmrig::Variant variantHint);
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;
@@ -103,4 +111,4 @@ private:
typedef std::vector<Pool> Pools;
#endif /* __POOL_H__ */
#endif /* XMRIG_POOL_H */

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 */