mirror of
https://github.com/feather-wallet/feather.git
synced 2024-11-17 09:47:36 +00:00
Merge pull request 'Mitigate target_height denial of service attack in wsMode' (#156) from tobtoht/feather:target_height into master
Reviewed-on: https://git.wownero.com/feather/feather/pulls/156
This commit is contained in:
commit
eb801ed9d4
7 changed files with 26 additions and 16 deletions
|
@ -459,7 +459,8 @@ void AppContext::onWSNodes(const QJsonArray &nodes) {
|
||||||
|
|
||||||
auto node = new FeatherNode(
|
auto node = new FeatherNode(
|
||||||
obj.value("address").toString(),
|
obj.value("address").toString(),
|
||||||
(unsigned int)obj.value("height").toInt(),
|
obj.value("height").toInt(),
|
||||||
|
obj.value("target_height").toInt(),
|
||||||
obj.value("online").toBool());
|
obj.value("online").toBool());
|
||||||
QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node);
|
QSharedPointer<FeatherNode> r = QSharedPointer<FeatherNode>(node);
|
||||||
l.append(r);
|
l.append(r);
|
||||||
|
|
|
@ -174,7 +174,7 @@ private:
|
||||||
const unsigned int m_donationBoundary = 15;
|
const unsigned int m_donationBoundary = 15;
|
||||||
UtilsNetworking *m_utilsNetworkingNodes;
|
UtilsNetworking *m_utilsNetworkingNodes;
|
||||||
QTimer *m_storeTimer = new QTimer(this);
|
QTimer *m_storeTimer = new QTimer(this);
|
||||||
QUrl m_wsUrl = QUrl(QStringLiteral("ws://dtg2clrd6iand4mwp2x6nhbqd3nqbxlbiw65f6vkwmmutxy2sijsnjyd.onion/ws"));
|
QUrl m_wsUrl = QUrl(QStringLiteral("ws://7e6egbawekbkxzkv4244pqeqgoo4axko2imgjbedwnn6s5yb6b7oliqd.onion/ws"));
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEATHER_APPCONTEXT_H
|
#endif //FEATHER_APPCONTEXT_H
|
||||||
|
|
|
@ -97,7 +97,7 @@ QVariant NodeModel::headerData(int section, Qt::Orientation orientation, int rol
|
||||||
FeatherNode NodeModel::node(int row) {
|
FeatherNode NodeModel::node(int row) {
|
||||||
if (row < 0 || row >= m_nodes.size()) {
|
if (row < 0 || row >= m_nodes.size()) {
|
||||||
qCritical("%s: no reddit post for index %d", __FUNCTION__, row);
|
qCritical("%s: no reddit post for index %d", __FUNCTION__, row);
|
||||||
return FeatherNode("", 0, false);
|
return FeatherNode();
|
||||||
}
|
}
|
||||||
return m_nodes.at(row);
|
return m_nodes.at(row);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ Nodes::Nodes(AppContext *ctx, QNetworkAccessManager *networkAccessManager, QObje
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
m_ctx(ctx),
|
m_ctx(ctx),
|
||||||
m_networkAccessManager(networkAccessManager),
|
m_networkAccessManager(networkAccessManager),
|
||||||
m_connection(FeatherNode("", 0, false)),
|
m_connection(FeatherNode()),
|
||||||
modelWebsocket(new NodeModel(NodeSource::websocket, this)),
|
modelWebsocket(new NodeModel(NodeSource::websocket, this)),
|
||||||
modelCustom(new NodeModel(NodeSource::custom, this)) {
|
modelCustom(new NodeModel(NodeSource::custom, this)) {
|
||||||
this->loadConfig();
|
this->loadConfig();
|
||||||
|
@ -47,7 +47,7 @@ void Nodes::loadConfig() {
|
||||||
// load custom nodes
|
// load custom nodes
|
||||||
auto nodes = obj.value("custom").toArray();
|
auto nodes = obj.value("custom").toArray();
|
||||||
foreach (const QJsonValue &value, nodes) {
|
foreach (const QJsonValue &value, nodes) {
|
||||||
auto customNode = FeatherNode(value.toString(), 0, false);
|
auto customNode = FeatherNode(value.toString());
|
||||||
customNode.custom = true;
|
customNode.custom = true;
|
||||||
|
|
||||||
if(m_connection == customNode) {
|
if(m_connection == customNode) {
|
||||||
|
@ -63,7 +63,7 @@ void Nodes::loadConfig() {
|
||||||
// load cached websocket nodes
|
// load cached websocket nodes
|
||||||
auto ws = obj.value("ws").toArray();
|
auto ws = obj.value("ws").toArray();
|
||||||
foreach (const QJsonValue &value, ws) {
|
foreach (const QJsonValue &value, ws) {
|
||||||
auto wsNode = FeatherNode(value.toString(), 0, false);
|
auto wsNode = FeatherNode(value.toString());
|
||||||
wsNode.custom = false;
|
wsNode.custom = false;
|
||||||
wsNode.online = true; // assume online
|
wsNode.online = true; // assume online
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ void Nodes::onConnectionTimer() {
|
||||||
|
|
||||||
FeatherNode Nodes::pickEligibleNode() {
|
FeatherNode Nodes::pickEligibleNode() {
|
||||||
// Pick a node at random to connect to
|
// Pick a node at random to connect to
|
||||||
FeatherNode rtn("", 0, false);
|
auto rtn = FeatherNode();
|
||||||
NodeSource nodeSource = this->source();
|
NodeSource nodeSource = this->source();
|
||||||
auto wsMode = nodeSource == NodeSource::websocket;
|
auto wsMode = nodeSource == NodeSource::websocket;
|
||||||
auto nodes = wsMode ? m_websocketNodes : m_customNodes;
|
auto nodes = wsMode ? m_websocketNodes : m_customNodes;
|
||||||
|
@ -268,13 +268,20 @@ FeatherNode Nodes::pickEligibleNode() {
|
||||||
continue;
|
continue;
|
||||||
m_connectionAttempts.append(node.full);
|
m_connectionAttempts.append(node.full);
|
||||||
|
|
||||||
if (wsMode && !node.online)
|
if (wsMode) {
|
||||||
|
// Ignore offline nodes
|
||||||
|
if (!node.online)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Ignore nodes that are more than 25 blocks behind mode
|
// Ignore nodes that are more than 25 blocks behind mode
|
||||||
if (wsMode && node.height < (mode_height - 25))
|
if (node.height < (mode_height - 25))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Ignore nodes that say they aren't synchronized
|
||||||
|
if (node.target_height > node.height)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ enum NodeSource {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FeatherNode {
|
struct FeatherNode {
|
||||||
FeatherNode(QString _address, unsigned int height, bool online) : height(height), online(online){
|
explicit FeatherNode(QString _address = "", int height = 0, int target_height = 0, bool online = false)
|
||||||
|
: height(height), target_height(target_height), online(online){
|
||||||
// wonky ipv4/host parsing, should be fine(tm)(c).
|
// wonky ipv4/host parsing, should be fine(tm)(c).
|
||||||
if(_address.isEmpty()) return;
|
if(_address.isEmpty()) return;
|
||||||
if(_address.contains("https://")) {
|
if(_address.contains("https://")) {
|
||||||
|
@ -50,7 +51,8 @@ struct FeatherNode {
|
||||||
|
|
||||||
QString address;
|
QString address;
|
||||||
QString full;
|
QString full;
|
||||||
unsigned int height;
|
int height;
|
||||||
|
int target_height;
|
||||||
bool online = false;
|
bool online = false;
|
||||||
QString username;
|
QString username;
|
||||||
QString password;
|
QString password;
|
||||||
|
|
|
@ -176,7 +176,7 @@ void NodeWidget::onCustomAddClicked(){
|
||||||
if(newNodeText.isEmpty())
|
if(newNodeText.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto node = FeatherNode(newNodeText, 0, false);
|
auto node = FeatherNode(newNodeText);
|
||||||
node.custom = true;
|
node.custom = true;
|
||||||
nodesList.append(node);
|
nodesList.append(node);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ bool NetworkPage::validatePage() {
|
||||||
auto nodeText = ui->lineEdit_customNode->text().trimmed();
|
auto nodeText = ui->lineEdit_customNode->text().trimmed();
|
||||||
if(!nodeText.isEmpty()) {
|
if(!nodeText.isEmpty()) {
|
||||||
auto customNodes = m_ctx->nodes->customNodes();
|
auto customNodes = m_ctx->nodes->customNodes();
|
||||||
auto node = FeatherNode(nodeText, 0, false);
|
auto node = FeatherNode(nodeText);
|
||||||
customNodes.append(node);
|
customNodes.append(node);
|
||||||
m_ctx->setCustomNodes(customNodes);
|
m_ctx->setCustomNodes(customNodes);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue