55
66#include < netaddress.h>
77
8+ #include < crypto/common.h>
9+ #include < crypto/sha3.h>
810#include < hash.h>
11+ #include < prevector.h>
912#include < tinyformat.h>
1013#include < util/asmap.h>
1114#include < util/strencodings.h>
@@ -29,7 +32,18 @@ CNetAddr::BIP155Network CNetAddr::GetBIP155Network() const
2932 case NET_IPV6:
3033 return BIP155Network::IPV6;
3134 case NET_ONION:
32- return BIP155Network::TORV2;
35+ switch (m_addr.size ()) {
36+ case ADDR_TORV2_SIZE:
37+ return BIP155Network::TORV2;
38+ case ADDR_TORV3_SIZE:
39+ return BIP155Network::TORV3;
40+ default :
41+ assert (false );
42+ }
43+ case NET_I2P:
44+ return BIP155Network::I2P;
45+ case NET_CJDNS:
46+ return BIP155Network::CJDNS;
3347 case NET_INTERNAL: // should have been handled before calling this function
3448 case NET_UNROUTABLE: // m_net is never and should not be set to NET_UNROUTABLE
3549 case NET_MAX: // m_net is never and should not be set to NET_MAX
@@ -66,6 +80,30 @@ bool CNetAddr::SetNetFromBIP155Network(uint8_t possible_bip155_net, size_t addre
6680 throw std::ios_base::failure (
6781 strprintf (" BIP155 TORv2 address with length %u (should be %u)" , address_size,
6882 ADDR_TORV2_SIZE));
83+ case BIP155Network::TORV3:
84+ if (address_size == ADDR_TORV3_SIZE) {
85+ m_net = NET_ONION;
86+ return true ;
87+ }
88+ throw std::ios_base::failure (
89+ strprintf (" BIP155 TORv3 address with length %u (should be %u)" , address_size,
90+ ADDR_TORV3_SIZE));
91+ case BIP155Network::I2P:
92+ if (address_size == ADDR_I2P_SIZE) {
93+ m_net = NET_I2P;
94+ return true ;
95+ }
96+ throw std::ios_base::failure (
97+ strprintf (" BIP155 I2P address with length %u (should be %u)" , address_size,
98+ ADDR_I2P_SIZE));
99+ case BIP155Network::CJDNS:
100+ if (address_size == ADDR_CJDNS_SIZE) {
101+ m_net = NET_CJDNS;
102+ return true ;
103+ }
104+ throw std::ios_base::failure (
105+ strprintf (" BIP155 CJDNS address with length %u (should be %u)" , address_size,
106+ ADDR_CJDNS_SIZE));
69107 }
70108
71109 // Don't throw on addresses with unknown network ids (maybe from the future).
@@ -92,7 +130,13 @@ void CNetAddr::SetIP(const CNetAddr& ipIn)
92130 assert (ipIn.m_addr .size () == ADDR_IPV6_SIZE);
93131 break ;
94132 case NET_ONION:
95- assert (ipIn.m_addr .size () == ADDR_TORV2_SIZE);
133+ assert (ipIn.m_addr .size () == ADDR_TORV2_SIZE || ipIn.m_addr .size () == ADDR_TORV3_SIZE);
134+ break ;
135+ case NET_I2P:
136+ assert (ipIn.m_addr .size () == ADDR_I2P_SIZE);
137+ break ;
138+ case NET_CJDNS:
139+ assert (ipIn.m_addr .size () == ADDR_CJDNS_SIZE);
96140 break ;
97141 case NET_INTERNAL:
98142 assert (ipIn.m_addr .size () == ADDR_INTERNAL_SIZE);
@@ -150,24 +194,82 @@ bool CNetAddr::SetInternal(const std::string &name)
150194 return true ;
151195}
152196
197+ namespace torv3 {
198+ // https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt#n2135
199+ static constexpr size_t CHECKSUM_LEN = 2 ;
200+ static constexpr size_t VERSION_LEN = 1 ;
201+ static const unsigned char VERSION[] = " \x03 " ;
202+ static constexpr size_t TOTAL_LEN = ADDR_TORV3_SIZE + CHECKSUM_LEN + VERSION_LEN;
203+
204+ static void Checksum (Span<const uint8_t > addr_pubkey, uint8_t (&checksum)[CHECKSUM_LEN])
205+ {
206+ // TORv3 CHECKSUM = H(".onion checksum" | PUBKEY | VERSION)[:2]
207+ static const unsigned char prefix[] = " .onion checksum" ;
208+ static constexpr size_t prefix_len = 15 ;
209+
210+ SHA3_256 hasher;
211+
212+ hasher.Write (MakeSpan (prefix).first (prefix_len));
213+ hasher.Write (addr_pubkey);
214+ hasher.Write (MakeSpan (torv3::VERSION).first (torv3::VERSION_LEN));
215+
216+ uint8_t checksum_full[SHA3_256::OUTPUT_SIZE];
217+
218+ hasher.Finalize (checksum_full);
219+
220+ memcpy (checksum, checksum_full, sizeof (checksum));
221+ }
222+
223+ }; // namespace torv3
224+
153225/* *
154- * Parse a TORv2 address and set this object to it.
226+ * Parse a TOR address and set this object to it.
155227 *
156228 * @returns Whether or not the operation was successful.
157229 *
158230 * @see CNetAddr::IsTor()
159231 */
160- bool CNetAddr::SetSpecial (const std::string &strName )
232+ bool CNetAddr::SetSpecial (const std::string& str )
161233{
162- if (strName.size ()>6 && strName.substr (strName.size () - 6 , 6 ) == " .onion" ) {
163- std::vector<unsigned char > vchAddr = DecodeBase32 (strName.substr (0 , strName.size () - 6 ).c_str ());
164- if (vchAddr.size () != ADDR_TORV2_SIZE) {
234+ static const char * suffix{" .onion" };
235+ static constexpr size_t suffix_len{6 };
236+
237+ if (!ValidAsCString (str) || str.size () <= suffix_len ||
238+ str.substr (str.size () - suffix_len) != suffix) {
239+ return false ;
240+ }
241+
242+ bool invalid;
243+ const auto & input = DecodeBase32 (str.substr (0 , str.size () - suffix_len).c_str (), &invalid);
244+
245+ if (invalid) {
246+ return false ;
247+ }
248+
249+ switch (input.size ()) {
250+ case ADDR_TORV2_SIZE:
251+ m_net = NET_ONION;
252+ m_addr.assign (input.begin (), input.end ());
253+ return true ;
254+ case torv3::TOTAL_LEN: {
255+ Span<const uint8_t > input_pubkey{input.data (), ADDR_TORV3_SIZE};
256+ Span<const uint8_t > input_checksum{input.data () + ADDR_TORV3_SIZE, torv3::CHECKSUM_LEN};
257+ Span<const uint8_t > input_version{input.data () + ADDR_TORV3_SIZE + torv3::CHECKSUM_LEN, torv3::VERSION_LEN};
258+
259+ uint8_t calculated_checksum[torv3::CHECKSUM_LEN];
260+ torv3::Checksum (input_pubkey, calculated_checksum);
261+
262+ if (input_checksum != calculated_checksum ||
263+ input_version != MakeSpan (torv3::VERSION).first (torv3::VERSION_LEN)) {
165264 return false ;
166265 }
266+
167267 m_net = NET_ONION;
168- m_addr.assign (vchAddr .begin (), vchAddr .end ());
268+ m_addr.assign (input_pubkey .begin (), input_pubkey .end ());
169269 return true ;
170270 }
271+ }
272+
171273 return false ;
172274}
173275
@@ -284,13 +386,21 @@ bool CNetAddr::IsHeNet() const
284386}
285387
286388/* *
287- * @returns Whether or not this is a dummy address that maps an onion address
288- * into IPv6.
289- *
389+ * Check whether this object represents a TOR address.
290390 * @see CNetAddr::SetSpecial(const std::string &)
291391 */
292392bool CNetAddr::IsTor () const { return m_net == NET_ONION; }
293393
394+ /* *
395+ * Check whether this object represents an I2P address.
396+ */
397+ bool CNetAddr::IsI2P () const { return m_net == NET_I2P; }
398+
399+ /* *
400+ * Check whether this object represents a CJDNS address.
401+ */
402+ bool CNetAddr::IsCJDNS () const { return m_net == NET_CJDNS; }
403+
294404bool CNetAddr::IsLocal () const
295405{
296406 // IPv4 loopback (127.0.0.0/8 or 0.0.0.0/8)
@@ -377,28 +487,72 @@ enum Network CNetAddr::GetNetwork() const
377487 return m_net;
378488}
379489
490+ static std::string IPv6ToString (Span<const uint8_t > a)
491+ {
492+ assert (a.size () == ADDR_IPV6_SIZE);
493+ // clang-format off
494+ return strprintf (" %x:%x:%x:%x:%x:%x:%x:%x" ,
495+ ReadBE16 (&a[0 ]),
496+ ReadBE16 (&a[2 ]),
497+ ReadBE16 (&a[4 ]),
498+ ReadBE16 (&a[6 ]),
499+ ReadBE16 (&a[8 ]),
500+ ReadBE16 (&a[10 ]),
501+ ReadBE16 (&a[12 ]),
502+ ReadBE16 (&a[14 ]));
503+ // clang-format on
504+ }
505+
380506std::string CNetAddr::ToStringIP () const
381507{
382- if (IsTor ())
383- return EncodeBase32 (m_addr) + " .onion" ;
384- if (IsInternal ())
508+ switch (m_net) {
509+ case NET_IPV4:
510+ case NET_IPV6: {
511+ CService serv (*this , 0 );
512+ struct sockaddr_storage sockaddr;
513+ socklen_t socklen = sizeof (sockaddr);
514+ if (serv.GetSockAddr ((struct sockaddr *)&sockaddr, &socklen)) {
515+ char name[1025 ] = " " ;
516+ if (!getnameinfo ((const struct sockaddr *)&sockaddr, socklen, name,
517+ sizeof (name), nullptr , 0 , NI_NUMERICHOST))
518+ return std::string (name);
519+ }
520+ if (m_net == NET_IPV4) {
521+ return strprintf (" %u.%u.%u.%u" , m_addr[0 ], m_addr[1 ], m_addr[2 ], m_addr[3 ]);
522+ }
523+ return IPv6ToString (m_addr);
524+ }
525+ case NET_ONION:
526+ switch (m_addr.size ()) {
527+ case ADDR_TORV2_SIZE:
528+ return EncodeBase32 (m_addr) + " .onion" ;
529+ case ADDR_TORV3_SIZE: {
530+
531+ uint8_t checksum[torv3::CHECKSUM_LEN];
532+ torv3::Checksum (m_addr, checksum);
533+
534+ // TORv3 onion_address = base32(PUBKEY | CHECKSUM | VERSION) + ".onion"
535+ prevector<torv3::TOTAL_LEN, uint8_t > address{m_addr.begin (), m_addr.end ()};
536+ address.insert (address.end (), checksum, checksum + torv3::CHECKSUM_LEN);
537+ address.insert (address.end (), torv3::VERSION, torv3::VERSION + torv3::VERSION_LEN);
538+
539+ return EncodeBase32 (address) + " .onion" ;
540+ }
541+ default :
542+ assert (false );
543+ }
544+ case NET_I2P:
545+ return EncodeBase32 (m_addr, false /* don't pad with = */ ) + " .b32.i2p" ;
546+ case NET_CJDNS:
547+ return IPv6ToString (m_addr);
548+ case NET_INTERNAL:
385549 return EncodeBase32 (m_addr) + " .internal" ;
386- CService serv (*this , 0 );
387- struct sockaddr_storage sockaddr;
388- socklen_t socklen = sizeof (sockaddr);
389- if (serv.GetSockAddr ((struct sockaddr *)&sockaddr, &socklen)) {
390- char name[1025 ] = " " ;
391- if (!getnameinfo ((const struct sockaddr *)&sockaddr, socklen, name, sizeof (name), nullptr , 0 , NI_NUMERICHOST))
392- return std::string (name);
393- }
394- if (IsIPv4 ())
395- return strprintf (" %u.%u.%u.%u" , m_addr[0 ], m_addr[1 ], m_addr[2 ], m_addr[3 ]);
396- assert (IsIPv6 ());
397- return strprintf (" %x:%x:%x:%x:%x:%x:%x:%x" ,
398- m_addr[0 ] << 8 | m_addr[1 ], m_addr[2 ] << 8 | m_addr[3 ],
399- m_addr[4 ] << 8 | m_addr[5 ], m_addr[6 ] << 8 | m_addr[7 ],
400- m_addr[8 ] << 8 | m_addr[9 ], m_addr[10 ] << 8 | m_addr[11 ],
401- m_addr[12 ] << 8 | m_addr[13 ], m_addr[14 ] << 8 | m_addr[15 ]);
550+ case NET_UNROUTABLE: // m_net is never and should not be set to NET_UNROUTABLE
551+ case NET_MAX: // m_net is never and should not be set to NET_MAX
552+ assert (false );
553+ } // no default case, so the compiler can warn about missing cases
554+
555+ assert (false );
402556}
403557
404558std::string CNetAddr::ToString () const
@@ -477,21 +631,22 @@ uint32_t CNetAddr::GetLinkedIPv4() const
477631 assert (false );
478632}
479633
480- uint32_t CNetAddr::GetNetClass () const {
481- uint32_t net_class = NET_IPV6;
482- if (IsLocal ()) {
483- net_class = 255 ;
484- }
634+ uint32_t CNetAddr::GetNetClass () const
635+ {
636+ // Make sure that if we return NET_IPV6, then IsIPv6() is true. The callers expect that.
637+
638+ // Check for "internal" first because such addresses are also !IsRoutable()
639+ // and we don't want to return NET_UNROUTABLE in that case.
485640 if (IsInternal ()) {
486- net_class = NET_INTERNAL;
487- } else if (!IsRoutable ()) {
488- net_class = NET_UNROUTABLE;
489- } else if (HasLinkedIPv4 ()) {
490- net_class = NET_IPV4;
491- } else if (IsTor ()) {
492- net_class = NET_ONION;
641+ return NET_INTERNAL;
493642 }
494- return net_class;
643+ if (!IsRoutable ()) {
644+ return NET_UNROUTABLE;
645+ }
646+ if (HasLinkedIPv4 ()) {
647+ return NET_IPV4;
648+ }
649+ return m_net;
495650}
496651
497652uint32_t CNetAddr::GetMappedAS (const std::vector<bool > &asmap) const {
@@ -566,7 +721,7 @@ std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) co
566721 vchRet.push_back ((ipv4 >> 24 ) & 0xFF );
567722 vchRet.push_back ((ipv4 >> 16 ) & 0xFF );
568723 return vchRet;
569- } else if (IsTor ()) {
724+ } else if (IsTor () || IsI2P () || IsCJDNS () ) {
570725 nBits = 4 ;
571726 } else if (IsHeNet ()) {
572727 // for he.net, use /36 groups
@@ -791,7 +946,7 @@ std::string CService::ToStringPort() const
791946
792947std::string CService::ToStringIPPort () const
793948{
794- if (IsIPv4 () || IsTor () || IsInternal ()) {
949+ if (IsIPv4 () || IsTor () || IsI2P () || IsInternal ()) {
795950 return ToStringIP () + " :" + ToStringPort ();
796951 } else {
797952 return " [" + ToStringIP () + " ]:" + ToStringPort ();
0 commit comments