Browse Source
0.13cfd519e
Add release note documentation (BtcDrak)6601ce5
protocol.h/cpp: Removes NetMsgType::ALERT (Thomas Kerin)ad72104
Formatting (BtcDrak)1b77471
Remove alert keys (BtcDrak)01fdfef
Remove `-alerts` option (BtcDrak)9206634
Update alert notification and GUI (BtcDrak)bbb9d1d
Remove p2p alert handling (BtcDrak)
Wladimir J. van der Laan
9 years ago
17 changed files with 38 additions and 673 deletions
@ -1,266 +0,0 @@ |
|||||||
// Copyright (c) 2010 Satoshi Nakamoto
|
|
||||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
|
||||||
// Distributed under the MIT software license, see the accompanying
|
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
#include "alert.h" |
|
||||||
|
|
||||||
#include "clientversion.h" |
|
||||||
#include "net.h" |
|
||||||
#include "pubkey.h" |
|
||||||
#include "timedata.h" |
|
||||||
#include "ui_interface.h" |
|
||||||
#include "util.h" |
|
||||||
#include "utilstrencodings.h" |
|
||||||
|
|
||||||
#include <stdint.h> |
|
||||||
#include <algorithm> |
|
||||||
#include <map> |
|
||||||
|
|
||||||
#include <boost/algorithm/string/classification.hpp> |
|
||||||
#include <boost/algorithm/string/replace.hpp> |
|
||||||
#include <boost/foreach.hpp> |
|
||||||
#include <boost/thread.hpp> |
|
||||||
|
|
||||||
using namespace std; |
|
||||||
|
|
||||||
map<uint256, CAlert> mapAlerts; |
|
||||||
CCriticalSection cs_mapAlerts; |
|
||||||
|
|
||||||
void CUnsignedAlert::SetNull() |
|
||||||
{ |
|
||||||
nVersion = 1; |
|
||||||
nRelayUntil = 0; |
|
||||||
nExpiration = 0; |
|
||||||
nID = 0; |
|
||||||
nCancel = 0; |
|
||||||
setCancel.clear(); |
|
||||||
nMinVer = 0; |
|
||||||
nMaxVer = 0; |
|
||||||
setSubVer.clear(); |
|
||||||
nPriority = 0; |
|
||||||
|
|
||||||
strComment.clear(); |
|
||||||
strStatusBar.clear(); |
|
||||||
strReserved.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
std::string CUnsignedAlert::ToString() const |
|
||||||
{ |
|
||||||
std::string strSetCancel; |
|
||||||
BOOST_FOREACH(int n, setCancel) |
|
||||||
strSetCancel += strprintf("%d ", n); |
|
||||||
std::string strSetSubVer; |
|
||||||
BOOST_FOREACH(const std::string& str, setSubVer) |
|
||||||
strSetSubVer += "\"" + str + "\" "; |
|
||||||
return strprintf( |
|
||||||
"CAlert(\n" |
|
||||||
" nVersion = %d\n" |
|
||||||
" nRelayUntil = %d\n" |
|
||||||
" nExpiration = %d\n" |
|
||||||
" nID = %d\n" |
|
||||||
" nCancel = %d\n" |
|
||||||
" setCancel = %s\n" |
|
||||||
" nMinVer = %d\n" |
|
||||||
" nMaxVer = %d\n" |
|
||||||
" setSubVer = %s\n" |
|
||||||
" nPriority = %d\n" |
|
||||||
" strComment = \"%s\"\n" |
|
||||||
" strStatusBar = \"%s\"\n" |
|
||||||
")\n", |
|
||||||
nVersion, |
|
||||||
nRelayUntil, |
|
||||||
nExpiration, |
|
||||||
nID, |
|
||||||
nCancel, |
|
||||||
strSetCancel, |
|
||||||
nMinVer, |
|
||||||
nMaxVer, |
|
||||||
strSetSubVer, |
|
||||||
nPriority, |
|
||||||
strComment, |
|
||||||
strStatusBar); |
|
||||||
} |
|
||||||
|
|
||||||
void CAlert::SetNull() |
|
||||||
{ |
|
||||||
CUnsignedAlert::SetNull(); |
|
||||||
vchMsg.clear(); |
|
||||||
vchSig.clear(); |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::IsNull() const |
|
||||||
{ |
|
||||||
return (nExpiration == 0); |
|
||||||
} |
|
||||||
|
|
||||||
uint256 CAlert::GetHash() const |
|
||||||
{ |
|
||||||
return Hash(this->vchMsg.begin(), this->vchMsg.end()); |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::IsInEffect() const |
|
||||||
{ |
|
||||||
return (GetAdjustedTime() < nExpiration); |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::Cancels(const CAlert& alert) const |
|
||||||
{ |
|
||||||
if (!IsInEffect()) |
|
||||||
return false; // this was a no-op before 31403
|
|
||||||
return (alert.nID <= nCancel || setCancel.count(alert.nID)); |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const |
|
||||||
{ |
|
||||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
|
||||||
return (IsInEffect() && |
|
||||||
nMinVer <= nVersion && nVersion <= nMaxVer && |
|
||||||
(setSubVer.empty() || setSubVer.count(strSubVerIn))); |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::AppliesToMe() const |
|
||||||
{ |
|
||||||
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>())); |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::RelayTo(CNode* pnode) const |
|
||||||
{ |
|
||||||
if (!IsInEffect()) |
|
||||||
return false; |
|
||||||
// don't relay to nodes which haven't sent their version message
|
|
||||||
if (pnode->nVersion == 0) |
|
||||||
return false; |
|
||||||
// returns true if wasn't already contained in the set
|
|
||||||
if (pnode->setKnown.insert(GetHash()).second) |
|
||||||
{ |
|
||||||
if (AppliesTo(pnode->nVersion, pnode->strSubVer) || |
|
||||||
AppliesToMe() || |
|
||||||
GetAdjustedTime() < nRelayUntil) |
|
||||||
{ |
|
||||||
pnode->PushMessage(NetMsgType::ALERT, *this); |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::CheckSignature(const std::vector<unsigned char>& alertKey) const |
|
||||||
{ |
|
||||||
CPubKey key(alertKey); |
|
||||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) |
|
||||||
return error("CAlert::CheckSignature(): verify signature failed"); |
|
||||||
|
|
||||||
// Now unserialize the data
|
|
||||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); |
|
||||||
sMsg >> *(CUnsignedAlert*)this; |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
CAlert CAlert::getAlertByHash(const uint256 &hash) |
|
||||||
{ |
|
||||||
CAlert retval; |
|
||||||
{ |
|
||||||
LOCK(cs_mapAlerts); |
|
||||||
map<uint256, CAlert>::iterator mi = mapAlerts.find(hash); |
|
||||||
if(mi != mapAlerts.end()) |
|
||||||
retval = mi->second; |
|
||||||
} |
|
||||||
return retval; |
|
||||||
} |
|
||||||
|
|
||||||
bool CAlert::ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread) |
|
||||||
{ |
|
||||||
if (!CheckSignature(alertKey)) |
|
||||||
return false; |
|
||||||
if (!IsInEffect()) |
|
||||||
return false; |
|
||||||
|
|
||||||
// alert.nID=max is reserved for if the alert key is
|
|
||||||
// compromised. It must have a pre-defined message,
|
|
||||||
// must never expire, must apply to all versions,
|
|
||||||
// and must cancel all previous
|
|
||||||
// alerts or it will be ignored (so an attacker can't
|
|
||||||
// send an "everything is OK, don't panic" version that
|
|
||||||
// cannot be overridden):
|
|
||||||
int maxInt = std::numeric_limits<int>::max(); |
|
||||||
if (nID == maxInt) |
|
||||||
{ |
|
||||||
if (!( |
|
||||||
nExpiration == maxInt && |
|
||||||
nCancel == (maxInt-1) && |
|
||||||
nMinVer == 0 && |
|
||||||
nMaxVer == maxInt && |
|
||||||
setSubVer.empty() && |
|
||||||
nPriority == maxInt && |
|
||||||
strStatusBar == "URGENT: Alert key compromised, upgrade required" |
|
||||||
)) |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
{ |
|
||||||
LOCK(cs_mapAlerts); |
|
||||||
// Cancel previous alerts
|
|
||||||
for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) |
|
||||||
{ |
|
||||||
const CAlert& alert = (*mi).second; |
|
||||||
if (Cancels(alert)) |
|
||||||
{ |
|
||||||
LogPrint("alert", "cancelling alert %d\n", alert.nID); |
|
||||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); |
|
||||||
mapAlerts.erase(mi++); |
|
||||||
} |
|
||||||
else if (!alert.IsInEffect()) |
|
||||||
{ |
|
||||||
LogPrint("alert", "expiring alert %d\n", alert.nID); |
|
||||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); |
|
||||||
mapAlerts.erase(mi++); |
|
||||||
} |
|
||||||
else |
|
||||||
mi++; |
|
||||||
} |
|
||||||
|
|
||||||
// Check if this alert has been cancelled
|
|
||||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) |
|
||||||
{ |
|
||||||
const CAlert& alert = item.second; |
|
||||||
if (alert.Cancels(*this)) |
|
||||||
{ |
|
||||||
LogPrint("alert", "alert already cancelled by %d\n", alert.nID); |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Add to mapAlerts
|
|
||||||
mapAlerts.insert(make_pair(GetHash(), *this)); |
|
||||||
// Notify UI and -alertnotify if it applies to me
|
|
||||||
if(AppliesToMe()) |
|
||||||
{ |
|
||||||
uiInterface.NotifyAlertChanged(GetHash(), CT_NEW); |
|
||||||
Notify(strStatusBar, fThread); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
void |
|
||||||
CAlert::Notify(const std::string& strMessage, bool fThread) |
|
||||||
{ |
|
||||||
std::string strCmd = GetArg("-alertnotify", ""); |
|
||||||
if (strCmd.empty()) return; |
|
||||||
|
|
||||||
// Alert text should be plain ascii coming from a trusted source, but to
|
|
||||||
// be safe we first strip anything not in safeChars, then add single quotes around
|
|
||||||
// the whole string before passing it to the shell:
|
|
||||||
std::string singleQuote("'"); |
|
||||||
std::string safeStatus = SanitizeString(strMessage); |
|
||||||
safeStatus = singleQuote+safeStatus+singleQuote; |
|
||||||
boost::replace_all(strCmd, "%s", safeStatus); |
|
||||||
|
|
||||||
if (fThread) |
|
||||||
boost::thread t(runCommand, strCmd); // thread runs free
|
|
||||||
else |
|
||||||
runCommand(strCmd); |
|
||||||
} |
|
@ -1,113 +0,0 @@ |
|||||||
// Copyright (c) 2010 Satoshi Nakamoto
|
|
||||||
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
|
||||||
// Distributed under the MIT software license, see the accompanying
|
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
||||||
|
|
||||||
#ifndef BITCOIN_ALERT_H |
|
||||||
#define BITCOIN_ALERT_H |
|
||||||
|
|
||||||
#include "serialize.h" |
|
||||||
#include "sync.h" |
|
||||||
|
|
||||||
#include <map> |
|
||||||
#include <set> |
|
||||||
#include <stdint.h> |
|
||||||
#include <string> |
|
||||||
|
|
||||||
class CAlert; |
|
||||||
class CNode; |
|
||||||
class uint256; |
|
||||||
|
|
||||||
extern std::map<uint256, CAlert> mapAlerts; |
|
||||||
extern CCriticalSection cs_mapAlerts; |
|
||||||
|
|
||||||
/** Alerts are for notifying old versions if they become too obsolete and
|
|
||||||
* need to upgrade. The message is displayed in the status bar. |
|
||||||
* Alert messages are broadcast as a vector of signed data. Unserializing may |
|
||||||
* not read the entire buffer if the alert is for a newer version, but older |
|
||||||
* versions can still relay the original data. |
|
||||||
*/ |
|
||||||
class CUnsignedAlert |
|
||||||
{ |
|
||||||
public: |
|
||||||
int nVersion; |
|
||||||
int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
|
|
||||||
int64_t nExpiration; |
|
||||||
int nID; |
|
||||||
int nCancel; |
|
||||||
std::set<int> setCancel; |
|
||||||
int nMinVer; // lowest version inclusive
|
|
||||||
int nMaxVer; // highest version inclusive
|
|
||||||
std::set<std::string> setSubVer; // empty matches all
|
|
||||||
int nPriority; |
|
||||||
|
|
||||||
// Actions
|
|
||||||
std::string strComment; |
|
||||||
std::string strStatusBar; |
|
||||||
std::string strReserved; |
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS; |
|
||||||
|
|
||||||
template <typename Stream, typename Operation> |
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
|
||||||
READWRITE(this->nVersion); |
|
||||||
nVersion = this->nVersion; |
|
||||||
READWRITE(nRelayUntil); |
|
||||||
READWRITE(nExpiration); |
|
||||||
READWRITE(nID); |
|
||||||
READWRITE(nCancel); |
|
||||||
READWRITE(setCancel); |
|
||||||
READWRITE(nMinVer); |
|
||||||
READWRITE(nMaxVer); |
|
||||||
READWRITE(setSubVer); |
|
||||||
READWRITE(nPriority); |
|
||||||
|
|
||||||
READWRITE(LIMITED_STRING(strComment, 65536)); |
|
||||||
READWRITE(LIMITED_STRING(strStatusBar, 256)); |
|
||||||
READWRITE(LIMITED_STRING(strReserved, 256)); |
|
||||||
} |
|
||||||
|
|
||||||
void SetNull(); |
|
||||||
|
|
||||||
std::string ToString() const; |
|
||||||
}; |
|
||||||
|
|
||||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */ |
|
||||||
class CAlert : public CUnsignedAlert |
|
||||||
{ |
|
||||||
public: |
|
||||||
std::vector<unsigned char> vchMsg; |
|
||||||
std::vector<unsigned char> vchSig; |
|
||||||
|
|
||||||
CAlert() |
|
||||||
{ |
|
||||||
SetNull(); |
|
||||||
} |
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS; |
|
||||||
|
|
||||||
template <typename Stream, typename Operation> |
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { |
|
||||||
READWRITE(vchMsg); |
|
||||||
READWRITE(vchSig); |
|
||||||
} |
|
||||||
|
|
||||||
void SetNull(); |
|
||||||
bool IsNull() const; |
|
||||||
uint256 GetHash() const; |
|
||||||
bool IsInEffect() const; |
|
||||||
bool Cancels(const CAlert& alert) const; |
|
||||||
bool AppliesTo(int nVersion, const std::string& strSubVerIn) const; |
|
||||||
bool AppliesToMe() const; |
|
||||||
bool RelayTo(CNode* pnode) const; |
|
||||||
bool CheckSignature(const std::vector<unsigned char>& alertKey) const; |
|
||||||
bool ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread
|
|
||||||
static void Notify(const std::string& strMessage, bool fThread); |
|
||||||
|
|
||||||
/*
|
|
||||||
* Get copy of (active) alert object by hash. Returns a null alert if it is not found. |
|
||||||
*/ |
|
||||||
static CAlert getAlertByHash(const uint256 &hash); |
|
||||||
}; |
|
||||||
|
|
||||||
#endif // BITCOIN_ALERT_H
|
|
Binary file not shown.
Loading…
Reference in new issue