upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nostr.cpp27
1 files changed, 21 insertions, 6 deletions
diff --git a/src/nostr.cpp b/src/nostr.cpp
index 009edd1..6f3b6a7 100644
--- a/src/nostr.cpp
+++ b/src/nostr.cpp
@@ -398,6 +398,12 @@ static bool BuildSignedEvent(CNostrKey& key, int kind, const json& tags,
398// 398//
399// Minimal WebSocket client over TLS (wss) or TCP (ws), blocking with timeout. 399// Minimal WebSocket client over TLS (wss) or TCP (ws), blocking with timeout.
400// 400//
401// Ceilings on what a relay may make this node allocate. Nostr events are
402// small -- relays themselves usually refuse anything over a few hundred KB --
403// so these are generous, and they bound an otherwise attacker-chosen size.
404static const uint64 MAX_WS_FRAME = 1 << 20; // 1 MiB per frame
405static const uint64 MAX_WS_MESSAGE = 4 << 20; // 4 MiB reassembled
406
401class CWebSocket 407class CWebSocket
402{ 408{
403public: 409public:
@@ -597,6 +603,14 @@ public:
597 len = 0; 603 len = 0;
598 for (int i = 0; i < 8; i++) len = (len << 8) | e[i]; 604 for (int i = 0; i < 8; i++) len = (len << 8) | e[i];
599 } 605 }
606 // The length is whatever the relay says it is, and these are public
607 // relays the node does not control. Unbounded, a single frame header
608 // claiming 2^40 bytes makes the node allocate until it dies -- and
609 // reassembly across continuation frames grows without limit even
610 // when each frame is small. Cap both, and refuse anything that will
611 // not survive the int narrowing ReadN takes.
612 if (len > MAX_WS_FRAME) return false;
613
600 unsigned char mask[4] = {0,0,0,0}; 614 unsigned char mask[4] = {0,0,0,0};
601 if (masked && !ReadN((char*)mask, 4)) return false; 615 if (masked && !ReadN((char*)mask, 4)) return false;
602 616
@@ -610,6 +624,7 @@ public:
610 if (opcode == 0x8) return false; // close 624 if (opcode == 0x8) return false; // close
611 if (opcode == 0x9) { SendPong(payload); continue; } // ping 625 if (opcode == 0x9) { SendPong(payload); continue; } // ping
612 if (opcode == 0xA) continue; // pong 626 if (opcode == 0xA) continue; // pong
627 if (out.size() + payload.size() > MAX_WS_MESSAGE) return false;
613 out += payload; // text/continuation 628 out += payload; // text/continuation
614 if (fin) return true; 629 if (fin) return true;
615 } 630 }
@@ -847,7 +862,7 @@ bool BtfQueryPoolAnnouncement(const std::string& poolBtfAddr, BtfPoolAnnouncemen
847 break; 862 break;
848 json j; 863 json j;
849 try { j = json::parse(msg); } catch (...) { continue; } 864 try { j = json::parse(msg); } catch (...) { continue; }
850 if (!j.is_array() || j.empty()) continue; 865 if (!j.is_array() || j.empty() || !j[0].is_string()) continue;
851 string type = j[0].get<string>(); 866 string type = j[0].get<string>();
852 if (type == "EVENT" && j.size() >= 3) 867 if (type == "EVENT" && j.size() >= 3)
853 { 868 {
@@ -957,7 +972,7 @@ static bool ResolveDescriptor(CWebSocket& ws, void* ctx, const string& btfAddr,
957 break; 972 break;
958 json j; 973 json j;
959 try { j = json::parse(msg); } catch (...) { continue; } 974 try { j = json::parse(msg); } catch (...) { continue; }
960 if (!j.is_array() || j.empty()) continue; 975 if (!j.is_array() || j.empty() || !j[0].is_string()) continue;
961 string t = j[0].get<string>(); 976 string t = j[0].get<string>();
962 if (t == "EVENT" && j.size() >= 3) 977 if (t == "EVENT" && j.size() >= 3)
963 { 978 {
@@ -1068,7 +1083,7 @@ bool BtfResolveMany(const std::vector<std::string>& btfAddrs,
1068 break; 1083 break;
1069 json j; 1084 json j;
1070 try { j = json::parse(msg); } catch (...) { continue; } 1085 try { j = json::parse(msg); } catch (...) { continue; }
1071 if (!j.is_array() || j.empty()) continue; 1086 if (!j.is_array() || j.empty() || !j[0].is_string()) continue;
1072 string t = j[0].get<string>(); 1087 string t = j[0].get<string>();
1073 if (t == "EVENT" && j.size() >= 3) 1088 if (t == "EVENT" && j.size() >= 3)
1074 { 1089 {
@@ -1144,7 +1159,7 @@ static bool SeedFromRelay(CNostrKey& key, const string& relay)
1144 break; 1159 break;
1145 json j; 1160 json j;
1146 try { j = json::parse(msg); } catch (...) { continue; } 1161 try { j = json::parse(msg); } catch (...) { continue; }
1147 if (!j.is_array() || j.empty()) continue; 1162 if (!j.is_array() || j.empty() || !j[0].is_string()) continue;
1148 string type = j[0].get<string>(); 1163 string type = j[0].get<string>();
1149 if (type == "EVENT" && j.size() >= 3) 1164 if (type == "EVENT" && j.size() >= 3)
1150 { 1165 {
@@ -1194,7 +1209,7 @@ static bool SeedFromRelay(CNostrKey& key, const string& relay)
1194 break; 1209 break;
1195 json j; 1210 json j;
1196 try { j = json::parse(msg); } catch (...) { continue; } 1211 try { j = json::parse(msg); } catch (...) { continue; }
1197 if (!j.is_array() || j.empty()) continue; 1212 if (!j.is_array() || j.empty() || !j[0].is_string()) continue;
1198 string type = j[0].get<string>(); 1213 string type = j[0].get<string>();
1199 if (type == "EVENT" && j.size() >= 3) 1214 if (type == "EVENT" && j.size() >= 3)
1200 { 1215 {
@@ -1234,7 +1249,7 @@ static bool SeedFromRelay(CNostrKey& key, const string& relay)
1234 break; 1249 break;
1235 json j; 1250 json j;
1236 try { j = json::parse(msg); } catch (...) { continue; } 1251 try { j = json::parse(msg); } catch (...) { continue; }
1237 if (!j.is_array() || j.empty()) continue; 1252 if (!j.is_array() || j.empty() || !j[0].is_string()) continue;
1238 string type = j[0].get<string>(); 1253 string type = j[0].get<string>();
1239 if (type == "EVENT" && j.size() >= 3) 1254 if (type == "EVENT" && j.size() >= 3)
1240 HandlePoolAnnouncement(j[2]); 1255 HandlePoolAnnouncement(j[2]);