diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-08-19 18:17:06 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-08-19 22:48:27 +0000 |
| commit | 11766bec0ea465da263f78a6f473ca792da59280 (patch) | |
| tree | f07c7eecabdf6a0b5f2299447dcf957472e7ef58 /src/market.h | |
| parent | 88d30ade28d6836e64d0157da57896bdb320e8a2 (diff) | |
net: stop serving the 2009 marketplace to anonymous peers
Four inherited handlers took attacker-controlled input and wrote to disk
with nothing authorising it. None of them had a caller left anywhere in
the tree, so all four were reachable only from the outside.
checkorder called GenerateNewKey() -- AddKey(), a wallet.dat write -- for
any peer that asked, and handed back the pubkey. Its comment claims the
cache keeps one key per ip, and on a 2009 network of routable addresses
it did. Not here: inbound peers arrive through a rendezvous tunnel and
are tagged by BtfMarkerAddr() over three random bytes, so addr.ip is
fresh every connection and the cache never hits. Reconnect in a loop and
the node mints a key per connection, none of them in any backup taken
beforehand, which for a pre-BIP32 wallet is how coins go missing. The map
holding them was static and never trimmed.
submitorder AddToWallet()'d a CWalletTx from any peer that sent one. It
had to be a valid transaction; it did not have to be ours.
review checked a signature the sender made with its own key, which proves
possession and authorises nothing, then appended to reviews.dat by
reading the whole vector, pushing one entry and writing it all back --
quadratic disk on an unbounded map<string,string> off the socket -- then
walked a link graph the same peer supplied and relayed the message to
every other node.
reply dispatched into CRequestTracker. Nothing ever called PushRequest,
so the table was permanently empty and the handler was a parser and
nothing else.
Removed with the subsystem behind them: market.cpp, CProduct, CReview,
CUser, CReviewDB, the advert publish templates and the subscribe channel
machinery, none of which had an inbound handler either. MSG_REVIEW,
MSG_PRODUCT and MSG_TABLE stay in the inv enum, unserved: CInv puts type
on the wire as an integer and MSG_TX and MSG_BLOCK are shared with every
other node.
Unknown commands are already ignored for extensibility, so peers still
running these lose nothing but an answer they never asked for. Verified
by a clean build of bitflash-node.
(cherry picked from commit ad9c393866c007a115f32d70a9017ce91066a7d1)
Diffstat (limited to 'src/market.h')
| -rw-r--r-- | src/market.h | 182 |
1 files changed, 0 insertions, 182 deletions
diff --git a/src/market.h b/src/market.h deleted file mode 100644 index b5c8b3b..0000000 --- a/src/market.h +++ /dev/null | |||
| @@ -1,182 +0,0 @@ | |||
| 1 | // Copyright (c) 2009 Satoshi Nakamoto | ||
| 2 | // Distributed under the MIT/X11 software license, see the accompanying | ||
| 3 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. | ||
| 4 | |||
| 5 | class CUser; | ||
| 6 | class CReview; | ||
| 7 | class CProduct; | ||
| 8 | |||
| 9 | static const unsigned int nFlowthroughRate = 2; | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | bool AdvertInsert(const CProduct& product); | ||
| 15 | void AdvertErase(const CProduct& product); | ||
| 16 | bool AddAtomsAndPropagate(uint256 hashUserStart, const vector<unsigned short>& vAtoms, bool fOrigin); | ||
| 17 | |||
| 18 | |||
| 19 | |||
| 20 | |||
| 21 | |||
| 22 | |||
| 23 | |||
| 24 | |||
| 25 | class CUser | ||
| 26 | { | ||
| 27 | public: | ||
| 28 | vector<unsigned short> vAtomsIn; | ||
| 29 | vector<unsigned short> vAtomsNew; | ||
| 30 | vector<unsigned short> vAtomsOut; | ||
| 31 | vector<uint256> vLinksOut; | ||
| 32 | |||
| 33 | CUser() | ||
| 34 | { | ||
| 35 | } | ||
| 36 | |||
| 37 | IMPLEMENT_SERIALIZE | ||
| 38 | ( | ||
| 39 | if (!(nType & SER_GETHASH)) | ||
| 40 | READWRITE(nVersion); | ||
| 41 | READWRITE(vAtomsIn); | ||
| 42 | READWRITE(vAtomsNew); | ||
| 43 | READWRITE(vAtomsOut); | ||
| 44 | READWRITE(vLinksOut); | ||
| 45 | ) | ||
| 46 | |||
| 47 | void SetNull() | ||
| 48 | { | ||
| 49 | vAtomsIn.clear(); | ||
| 50 | vAtomsNew.clear(); | ||
| 51 | vAtomsOut.clear(); | ||
| 52 | vLinksOut.clear(); | ||
| 53 | } | ||
| 54 | |||
| 55 | uint256 GetHash() const { return SerializeHash(*this); } | ||
| 56 | |||
| 57 | |||
| 58 | int GetAtomCount() const | ||
| 59 | { | ||
| 60 | return (vAtomsIn.size() + vAtomsNew.size()); | ||
| 61 | } | ||
| 62 | |||
| 63 | void AddAtom(unsigned short nAtom, bool fOrigin); | ||
| 64 | }; | ||
| 65 | |||
| 66 | |||
| 67 | |||
| 68 | |||
| 69 | |||
| 70 | |||
| 71 | |||
| 72 | class CReview | ||
| 73 | { | ||
| 74 | public: | ||
| 75 | int nVersion; | ||
| 76 | uint256 hashTo; | ||
| 77 | map<string, string> mapValue; | ||
| 78 | vector<unsigned char> vchPubKeyFrom; | ||
| 79 | vector<unsigned char> vchSig; | ||
| 80 | |||
| 81 | // memory only | ||
| 82 | unsigned int nTime; | ||
| 83 | int nAtoms; | ||
| 84 | |||
| 85 | |||
| 86 | CReview() | ||
| 87 | { | ||
| 88 | nVersion = 1; | ||
| 89 | hashTo = 0; | ||
| 90 | nTime = 0; | ||
| 91 | nAtoms = 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | IMPLEMENT_SERIALIZE | ||
| 95 | ( | ||
| 96 | READWRITE(this->nVersion); | ||
| 97 | nVersion = this->nVersion; | ||
| 98 | if (!(nType & SER_DISK)) | ||
| 99 | READWRITE(hashTo); | ||
| 100 | READWRITE(mapValue); | ||
| 101 | READWRITE(vchPubKeyFrom); | ||
| 102 | if (!(nType & SER_GETHASH)) | ||
| 103 | READWRITE(vchSig); | ||
| 104 | ) | ||
| 105 | |||
| 106 | uint256 GetHash() const { return SerializeHash(*this); } | ||
| 107 | uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); } | ||
| 108 | uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); } | ||
| 109 | |||
| 110 | |||
| 111 | bool AcceptReview(); | ||
| 112 | }; | ||
| 113 | |||
| 114 | |||
| 115 | |||
| 116 | |||
| 117 | |||
| 118 | |||
| 119 | |||
| 120 | class CProduct | ||
| 121 | { | ||
| 122 | public: | ||
| 123 | int nVersion; | ||
| 124 | CAddress addr; | ||
| 125 | map<string, string> mapValue; | ||
| 126 | map<string, string> mapDetails; | ||
| 127 | vector<pair<string, string> > vOrderForm; | ||
| 128 | unsigned int nSequence; | ||
| 129 | vector<unsigned char> vchPubKeyFrom; | ||
| 130 | vector<unsigned char> vchSig; | ||
| 131 | |||
| 132 | // disk only | ||
| 133 | int nAtoms; | ||
| 134 | |||
| 135 | // memory only | ||
| 136 | set<unsigned int> setSources; | ||
| 137 | |||
| 138 | CProduct() | ||
| 139 | { | ||
| 140 | nVersion = 1; | ||
| 141 | nAtoms = 0; | ||
| 142 | nSequence = 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | IMPLEMENT_SERIALIZE | ||
| 146 | ( | ||
| 147 | READWRITE(this->nVersion); | ||
| 148 | nVersion = this->nVersion; | ||
| 149 | READWRITE(addr); | ||
| 150 | READWRITE(mapValue); | ||
| 151 | if (!(nType & SER_GETHASH)) | ||
| 152 | { | ||
| 153 | READWRITE(mapDetails); | ||
| 154 | READWRITE(vOrderForm); | ||
| 155 | READWRITE(nSequence); | ||
| 156 | } | ||
| 157 | READWRITE(vchPubKeyFrom); | ||
| 158 | if (!(nType & SER_GETHASH)) | ||
| 159 | READWRITE(vchSig); | ||
| 160 | if (nType & SER_DISK) | ||
| 161 | READWRITE(nAtoms); | ||
| 162 | ) | ||
| 163 | |||
| 164 | uint256 GetHash() const { return SerializeHash(*this); } | ||
| 165 | uint256 GetSigHash() const { return SerializeHash(*this, SER_GETHASH|SER_SKIPSIG); } | ||
| 166 | uint256 GetUserHash() const { return Hash(vchPubKeyFrom.begin(), vchPubKeyFrom.end()); } | ||
| 167 | |||
| 168 | |||
| 169 | bool CheckSignature(); | ||
| 170 | bool CheckProduct(); | ||
| 171 | }; | ||
| 172 | |||
| 173 | |||
| 174 | |||
| 175 | |||
| 176 | |||
| 177 | |||
| 178 | |||
| 179 | |||
| 180 | extern map<uint256, CProduct> mapProducts; | ||
| 181 | extern CCriticalSection cs_mapProducts; | ||
| 182 | extern map<uint256, CProduct> mapMyProducts; | ||