-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b03b01b
commit 8314fcb
Showing
100 changed files
with
27,249 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,273 @@ | ||
// | ||
// Alert system | ||
// | ||
|
||
#include <algorithm> | ||
#include <boost/algorithm/string/classification.hpp> | ||
#include <boost/algorithm/string/replace.hpp> | ||
#include <boost/foreach.hpp> | ||
#include <map> | ||
|
||
#include "alert.h" | ||
#include "key.h" | ||
#include "net.h" | ||
#include "sync.h" | ||
#include "ui_interface.h" | ||
|
||
using namespace std; | ||
|
||
map<uint256, CAlert> mapAlerts; | ||
CCriticalSection cs_mapAlerts; | ||
|
||
static const char* pszMainKey = "0418d82f8b4b03e2a595cc8760b54e78be13dd02ace3d66bb8ed995df18e345f3dabd0befb758cd89a54139f068b9821916183db9cba1b2b4d005708a2fa60dab5"; | ||
|
||
// TestNet alerts pubKey | ||
static const char* pszTestKey = "04234c1964be26b751050675ac1e5804c77fd889cd0c631b4f7374f1b8679dc4091b0f35385e5c6686b9e2af855c6ddfc6d93fcfd5b73e636196409bb7c11de390"; | ||
|
||
// TestNet alerts private key | ||
// "308201130201010420b665cff1884e53da26376fd1b433812c9a5a8a4d5221533b15b9629789bb7e42a081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a14403420004234c1964be26b751050675ac1e5804c77fd889cd0c631b4f7374f1b8679dc4091b0f35385e5c6686b9e2af855c6ddfc6d93fcfd5b73e636196409bb7c11de390" | ||
|
||
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(std::string str, setSubVer) | ||
strSetSubVer += "\"" + str + "\" "; | ||
return strprintf( | ||
"CAlert(\n" | ||
" nVersion = %d\n" | ||
" nRelayUntil = %"PRId64"\n" | ||
" nExpiration = %"PRId64"\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.c_str(), | ||
nMinVer, | ||
nMaxVer, | ||
strSetSubVer.c_str(), | ||
nPriority, | ||
strComment.c_str(), | ||
strStatusBar.c_str()); | ||
} | ||
|
||
void CUnsignedAlert::print() const | ||
{ | ||
printf("%s", ToString().c_str()); | ||
} | ||
|
||
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, 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; | ||
// 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("alert", *this); | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
bool CAlert::CheckSignature() const | ||
{ | ||
CKey key; | ||
if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey))) | ||
return error("CAlert::CheckSignature() : SetPubKey failed"); | ||
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(bool fThread) | ||
{ | ||
if (!CheckSignature()) | ||
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)) | ||
{ | ||
printf("cancelling alert %d\n", alert.nID); | ||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); | ||
mapAlerts.erase(mi++); | ||
} | ||
else if (!alert.IsInEffect()) | ||
{ | ||
printf("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)) | ||
{ | ||
printf("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); | ||
std::string strCmd = GetArg("-alertnotify", ""); | ||
if (!strCmd.empty()) | ||
{ | ||
// 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("'"); | ||
// safeChars chosen to allow simple messages/URLs/email addresses, but avoid anything | ||
// even possibly remotely dangerous like & or > | ||
std::string safeChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890 .,;_/:?@"); | ||
std::string safeStatus; | ||
for (std::string::size_type i = 0; i < strStatusBar.size(); i++) | ||
{ | ||
if (safeChars.find(strStatusBar[i]) != std::string::npos) | ||
safeStatus.push_back(strStatusBar[i]); | ||
} | ||
safeStatus = singleQuote+safeStatus+singleQuote; | ||
boost::replace_all(strCmd, "%s", safeStatus); | ||
|
||
if (fThread) | ||
boost::thread t(runCommand, strCmd); // thread runs free | ||
else | ||
runCommand(strCmd); | ||
} | ||
} | ||
} | ||
|
||
printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
// Copyright (c) 2010 Satoshi Nakamoto | ||
// Copyright (c) 2009-2012 The Bitcoin developers | ||
// Distributed under the MIT/X11 software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#ifndef _BITCOINALERT_H_ | ||
#define _BITCOINALERT_H_ 1 | ||
|
||
#include <set> | ||
#include <string> | ||
|
||
#include "uint256.h" | ||
#include "util.h" | ||
|
||
class CNode; | ||
|
||
/** 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; | ||
|
||
IMPLEMENT_SERIALIZE | ||
( | ||
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(strComment); | ||
READWRITE(strStatusBar); | ||
READWRITE(strReserved); | ||
) | ||
|
||
void SetNull(); | ||
|
||
std::string ToString() const; | ||
void print() 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(); | ||
} | ||
|
||
IMPLEMENT_SERIALIZE | ||
( | ||
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, std::string strSubVerIn) const; | ||
bool AppliesToMe() const; | ||
bool RelayTo(CNode* pnode) const; | ||
bool CheckSignature() const; | ||
bool ProcessAlert(bool fThread = true); | ||
|
||
/* | ||
* Get copy of (active) alert object by hash. Returns a null alert if it is not found. | ||
*/ | ||
static CAlert getAlertByHash(const uint256 &hash); | ||
}; | ||
|
||
#endif |
Oops, something went wrong.