1 /* 2 * Copyright (c) 2013-2021, The PurpleI2P Project 3 * 4 * This file is part of Purple i2pd project and licensed under BSD3 5 * 6 * See full license text in LICENSE file at top of project tree 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include "I2PEndian.h" 12 #include <fstream> 13 #include <boost/lexical_cast.hpp> 14 #include <boost/make_shared.hpp> 15 #if (BOOST_VERSION >= 105300) 16 #include <boost/atomic.hpp> 17 #endif 18 #include "version.h" 19 #include "util.h" 20 #include "Crypto.h" 21 #include "Base.h" 22 #include "Timestamp.h" 23 #include "Log.h" 24 #include "NetDb.hpp" 25 #include "RouterContext.h" 26 #include "RouterInfo.h" 27 28 namespace i2p 29 { 30 namespace data 31 { RouterInfo()32 RouterInfo::RouterInfo (): m_Buffer (nullptr) 33 { 34 m_Addresses = boost::make_shared<Addresses>(); // create empty list 35 } 36 RouterInfo(const std::string & fullPath)37 RouterInfo::RouterInfo (const std::string& fullPath): 38 m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0), 39 m_ReachableTransports (0), m_Caps (0), m_Version (0) 40 { 41 m_Addresses = boost::make_shared<Addresses>(); // create empty list 42 m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; 43 ReadFromFile (fullPath); 44 } 45 RouterInfo(const uint8_t * buf,int len)46 RouterInfo::RouterInfo (const uint8_t * buf, int len): 47 m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), 48 m_ReachableTransports (0), m_Caps (0), m_Version (0) 49 { 50 m_Addresses = boost::make_shared<Addresses>(); // create empty list 51 if (len <= MAX_RI_BUFFER_SIZE) 52 { 53 m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; 54 memcpy (m_Buffer, buf, len); 55 m_BufferLen = len; 56 ReadFromBuffer (true); 57 } 58 else 59 { 60 LogPrint (eLogError, "RouterInfo: Buffer is too long ", len, ". Ignored"); 61 m_Buffer = nullptr; 62 m_IsUnreachable = true; 63 } 64 } 65 ~RouterInfo()66 RouterInfo::~RouterInfo () 67 { 68 delete[] m_Buffer; 69 } 70 Update(const uint8_t * buf,size_t len)71 void RouterInfo::Update (const uint8_t * buf, size_t len) 72 { 73 if (len > MAX_RI_BUFFER_SIZE) 74 { 75 LogPrint (eLogError, "RouterInfo: Buffer is too long ", len); 76 m_IsUnreachable = true; 77 return; 78 } 79 // verify signature since we have identity already 80 int l = len - m_RouterIdentity->GetSignatureLen (); 81 if (m_RouterIdentity->Verify (buf, l, buf + l)) 82 { 83 // clean up 84 m_IsUpdated = true; 85 m_IsUnreachable = false; 86 m_SupportedTransports = 0; 87 m_ReachableTransports = 0; 88 m_Caps = 0; 89 // don't clean up m_Addresses, it will be replaced in ReadFromStream 90 m_Properties.clear (); 91 // copy buffer 92 if (!m_Buffer) 93 m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; 94 memcpy (m_Buffer, buf, len); 95 m_BufferLen = len; 96 // skip identity 97 size_t identityLen = m_RouterIdentity->GetFullLen (); 98 // read new RI 99 std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen)); 100 ReadFromStream (str); 101 // don't delete buffer until saved to the file 102 } 103 else 104 { 105 LogPrint (eLogError, "RouterInfo: Signature verification failed"); 106 m_IsUnreachable = true; 107 } 108 } 109 SetRouterIdentity(std::shared_ptr<const IdentityEx> identity)110 void RouterInfo::SetRouterIdentity (std::shared_ptr<const IdentityEx> identity) 111 { 112 m_RouterIdentity = identity; 113 m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); 114 } 115 LoadFile(const std::string & fullPath)116 bool RouterInfo::LoadFile (const std::string& fullPath) 117 { 118 std::ifstream s(fullPath, std::ifstream::binary); 119 if (s.is_open ()) 120 { 121 s.seekg (0,std::ios::end); 122 m_BufferLen = s.tellg (); 123 if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE) 124 { 125 LogPrint(eLogError, "RouterInfo: File", fullPath, " is malformed"); 126 return false; 127 } 128 s.seekg(0, std::ios::beg); 129 if (!m_Buffer) m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; 130 s.read((char *)m_Buffer, m_BufferLen); 131 } 132 else 133 { 134 LogPrint (eLogError, "RouterInfo: Can't open file ", fullPath); 135 return false; 136 } 137 return true; 138 } 139 ReadFromFile(const std::string & fullPath)140 void RouterInfo::ReadFromFile (const std::string& fullPath) 141 { 142 if (LoadFile (fullPath)) 143 ReadFromBuffer (false); 144 else 145 m_IsUnreachable = true; 146 } 147 ReadFromBuffer(bool verifySignature)148 void RouterInfo::ReadFromBuffer (bool verifySignature) 149 { 150 m_RouterIdentity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen); 151 size_t identityLen = m_RouterIdentity->GetFullLen (); 152 if (identityLen >= m_BufferLen) 153 { 154 LogPrint (eLogError, "RouterInfo: Identity length ", identityLen, " exceeds buffer size ", m_BufferLen); 155 m_IsUnreachable = true; 156 return; 157 } 158 if (verifySignature) 159 { 160 // reject RSA signatures 161 if (m_RouterIdentity->IsRSA ()) 162 { 163 LogPrint (eLogError, "RouterInfo: RSA signature type is not allowed"); 164 m_IsUnreachable = true; 165 return; 166 } 167 // verify signature 168 int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); 169 if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l)) 170 { 171 LogPrint (eLogError, "RouterInfo: Signature verification failed"); 172 m_IsUnreachable = true; 173 return; 174 } 175 m_RouterIdentity->DropVerifier (); 176 } 177 // parse RI 178 std::stringstream str; 179 str.write ((const char *)m_Buffer + identityLen, m_BufferLen - identityLen); 180 ReadFromStream (str); 181 if (!str) 182 { 183 LogPrint (eLogError, "RouterInfo: Malformed message"); 184 m_IsUnreachable = true; 185 } 186 } 187 ReadFromStream(std::istream & s)188 void RouterInfo::ReadFromStream (std::istream& s) 189 { 190 if (!s) return; 191 m_Caps = 0; 192 s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); 193 m_Timestamp = be64toh (m_Timestamp); 194 // read addresses 195 auto addresses = boost::make_shared<Addresses>(); 196 uint8_t numAddresses; 197 s.read ((char *)&numAddresses, sizeof (numAddresses)); 198 addresses->reserve (numAddresses); 199 for (int i = 0; i < numAddresses; i++) 200 { 201 uint8_t supportedTransports = 0; 202 auto address = std::make_shared<Address>(); 203 uint8_t cost; // ignore 204 s.read ((char *)&cost, sizeof (cost)); 205 s.read ((char *)&address->date, sizeof (address->date)); 206 bool isHost = false, isIntroKey = false, isStaticKey = false; 207 char transportStyle[6]; 208 ReadString (transportStyle, 6, s); 209 if (!strncmp (transportStyle, "NTCP", 4)) // NTCP or NTCP2 210 { 211 address->transportStyle = eTransportNTCP; 212 address->ntcp2.reset (new NTCP2Ext ()); 213 } 214 else if (!strcmp (transportStyle, "SSU")) 215 { 216 address->transportStyle = eTransportSSU; 217 address->ssu.reset (new SSUExt ()); 218 address->ssu->mtu = 0; 219 } 220 else 221 address->transportStyle = eTransportUnknown; 222 address->caps = 0; 223 address->port = 0; 224 uint16_t size, r = 0; 225 s.read ((char *)&size, sizeof (size)); if (!s) return; 226 size = be16toh (size); 227 while (r < size) 228 { 229 char key[255], value[255]; 230 r += ReadString (key, 255, s); 231 s.seekg (1, std::ios_base::cur); r++; // = 232 r += ReadString (value, 255, s); 233 s.seekg (1, std::ios_base::cur); r++; // ; 234 if (!s) return; 235 if (!strcmp (key, "host")) 236 { 237 boost::system::error_code ecode; 238 address->host = boost::asio::ip::address::from_string (value, ecode); 239 if (!ecode && !address->host.is_unspecified ()) isHost = true; 240 } 241 else if (!strcmp (key, "port")) 242 address->port = boost::lexical_cast<int>(value); 243 else if (!strcmp (key, "mtu")) 244 { 245 if (address->ssu) 246 address->ssu->mtu = boost::lexical_cast<int>(value); 247 else 248 LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP"); 249 } 250 else if (!strcmp (key, "key")) 251 { 252 if (address->ssu) 253 isIntroKey = (Base64ToByteStream (value, strlen (value), address->ssu->key, 32) == 32); 254 else 255 LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP"); 256 } 257 else if (!strcmp (key, "caps")) 258 address->caps = ExtractAddressCaps (value); 259 else if (!strcmp (key, "s")) // ntcp2 static key 260 { 261 Base64ToByteStream (value, strlen (value), address->ntcp2->staticKey, 32); 262 isStaticKey = true; 263 } 264 else if (!strcmp (key, "i")) // ntcp2 iv 265 { 266 Base64ToByteStream (value, strlen (value), address->ntcp2->iv, 16); 267 address->published = true; // presence if "i" means "published" 268 } 269 else if (key[0] == 'i') 270 { 271 // introducers 272 if (!address->ssu) 273 { 274 LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped"); 275 continue; 276 } 277 size_t l = strlen(key); 278 unsigned char index = key[l-1] - '0'; // TODO: 279 key[l-1] = 0; 280 if (index > 9) 281 { 282 LogPrint (eLogError, "RouterInfo: Unexpected introducer's index ", index, " skipped"); 283 if (s) continue; else return; 284 } 285 if (index >= address->ssu->introducers.size ()) 286 { 287 if (address->ssu->introducers.empty ()) // first time 288 address->ssu->introducers.reserve (3); 289 address->ssu->introducers.resize (index + 1); 290 } 291 Introducer& introducer = address->ssu->introducers.at (index); 292 if (!strcmp (key, "ihost")) 293 { 294 boost::system::error_code ecode; 295 introducer.iHost = boost::asio::ip::address::from_string (value, ecode); 296 } 297 else if (!strcmp (key, "iport")) 298 introducer.iPort = boost::lexical_cast<int>(value); 299 else if (!strcmp (key, "itag")) 300 introducer.iTag = boost::lexical_cast<uint32_t>(value); 301 else if (!strcmp (key, "ikey")) 302 Base64ToByteStream (value, strlen (value), introducer.iKey, 32); 303 else if (!strcmp (key, "iexp")) 304 introducer.iExp = boost::lexical_cast<uint32_t>(value); 305 } 306 if (!s) return; 307 } 308 if (address->transportStyle == eTransportNTCP) 309 { 310 if (isStaticKey) 311 { 312 if (isHost) 313 { 314 if (address->host.is_v6 ()) 315 supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6); 316 else 317 supportedTransports |= eNTCP2V4; 318 m_ReachableTransports |= supportedTransports; 319 } 320 else if (!address->published) 321 { 322 if (address->caps) 323 { 324 if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4; 325 if (address->caps & AddressCaps::eV6) supportedTransports |= eNTCP2V6; 326 } 327 else 328 supportedTransports |= eNTCP2V4; // most likely, since we don't have host 329 } 330 } 331 } 332 else if (address->transportStyle == eTransportSSU) 333 { 334 if (isIntroKey) 335 { 336 if (isHost) 337 supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6; 338 else if (address->caps & AddressCaps::eV6) 339 { 340 supportedTransports |= eSSUV6; 341 if (address->caps & AddressCaps::eV4) supportedTransports |= eSSUV4; // in additional to v6 342 } 343 else 344 supportedTransports |= eSSUV4; // in case if host or 6 caps is not preasented, we assume 4 345 if (address->ssu && !address->ssu->introducers.empty ()) 346 { 347 // exclude invalid introducers 348 uint32_t ts = i2p::util::GetSecondsSinceEpoch (); 349 int numValid = 0; 350 for (auto& it: address->ssu->introducers) 351 { 352 if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT; 353 if (ts <= it.iExp && it.iPort > 0 && 354 ((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ()))) 355 numValid++; 356 else 357 it.iPort = 0; 358 } 359 if (numValid) 360 m_ReachableTransports |= supportedTransports; 361 else 362 address->ssu->introducers.resize (0); 363 } 364 else if (isHost && address->port) 365 { 366 address->published = true; 367 m_ReachableTransports |= supportedTransports; 368 } 369 } 370 } 371 if (supportedTransports) 372 { 373 addresses->push_back(address); 374 m_SupportedTransports |= supportedTransports; 375 } 376 } 377 #if (BOOST_VERSION >= 105300) 378 boost::atomic_store (&m_Addresses, addresses); 379 #else 380 m_Addresses = addresses; // race condition 381 #endif 382 // read peers 383 uint8_t numPeers; 384 s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; 385 s.seekg (numPeers*32, std::ios_base::cur); // TODO: read peers 386 // read properties 387 uint16_t size, r = 0; 388 s.read ((char *)&size, sizeof (size)); if (!s) return; 389 size = be16toh (size); 390 while (r < size) 391 { 392 char key[255], value[255]; 393 r += ReadString (key, 255, s); 394 s.seekg (1, std::ios_base::cur); r++; // = 395 r += ReadString (value, 255, s); 396 s.seekg (1, std::ios_base::cur); r++; // ; 397 if (!s) return; 398 m_Properties[key] = value; 399 400 // extract caps 401 if (!strcmp (key, "caps")) 402 ExtractCaps (value); 403 // extract version 404 else if (!strcmp (key, ROUTER_INFO_PROPERTY_VERSION)) 405 { 406 m_Version = 0; 407 char * ch = value; 408 while (*ch) 409 { 410 if (*ch >= '0' && *ch <= '9') 411 { 412 m_Version *= 10; 413 m_Version += (*ch - '0'); 414 } 415 ch++; 416 } 417 } 418 // check netId 419 else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ()) 420 { 421 LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); 422 m_IsUnreachable = true; 423 } 424 // family 425 else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY)) 426 { 427 m_Family = value; 428 boost::to_lower (m_Family); 429 } 430 else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY_SIG)) 431 { 432 if (!netdb.GetFamilies ().VerifyFamily (m_Family, GetIdentHash (), value)) 433 { 434 LogPrint (eLogWarning, "RouterInfo: Family signature verification failed"); 435 m_Family.clear (); 436 } 437 } 438 439 if (!s) return; 440 } 441 442 if (!m_SupportedTransports) 443 SetUnreachable (true); 444 } 445 IsFamily(const std::string & fam) const446 bool RouterInfo::IsFamily(const std::string & fam) const 447 { 448 return m_Family == fam; 449 } 450 ExtractCaps(const char * value)451 void RouterInfo::ExtractCaps (const char * value) 452 { 453 const char * cap = value; 454 while (*cap) 455 { 456 switch (*cap) 457 { 458 case CAPS_FLAG_FLOODFILL: 459 m_Caps |= Caps::eFloodfill; 460 break; 461 case CAPS_FLAG_HIGH_BANDWIDTH1: 462 case CAPS_FLAG_HIGH_BANDWIDTH2: 463 case CAPS_FLAG_HIGH_BANDWIDTH3: 464 m_Caps |= Caps::eHighBandwidth; 465 break; 466 case CAPS_FLAG_EXTRA_BANDWIDTH1: 467 case CAPS_FLAG_EXTRA_BANDWIDTH2: 468 m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth; 469 break; 470 case CAPS_FLAG_HIDDEN: 471 m_Caps |= Caps::eHidden; 472 break; 473 case CAPS_FLAG_REACHABLE: 474 m_Caps |= Caps::eReachable; 475 break; 476 case CAPS_FLAG_UNREACHABLE: 477 m_Caps |= Caps::eUnreachable; 478 break; 479 default: ; 480 } 481 cap++; 482 } 483 } 484 ExtractAddressCaps(const char * value) const485 uint8_t RouterInfo::ExtractAddressCaps (const char * value) const 486 { 487 uint8_t caps = 0; 488 const char * cap = value; 489 while (*cap) 490 { 491 switch (*cap) 492 { 493 case CAPS_FLAG_V4: 494 caps |= AddressCaps::eV4; 495 break; 496 case CAPS_FLAG_V6: 497 caps |= AddressCaps::eV6; 498 break; 499 case CAPS_FLAG_SSU_TESTING: 500 caps |= AddressCaps::eSSUTesting; 501 break; 502 case CAPS_FLAG_SSU_INTRODUCER: 503 caps |= AddressCaps::eSSUIntroducer; 504 break; 505 default: ; 506 } 507 cap++; 508 } 509 return caps; 510 } 511 UpdateCapsProperty()512 void RouterInfo::UpdateCapsProperty () 513 { 514 std::string caps; 515 if (m_Caps & eFloodfill) 516 { 517 if (m_Caps & eExtraBandwidth) caps += (m_Caps & eHighBandwidth) ? 518 CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' 519 CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' 520 else 521 caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' 522 caps += CAPS_FLAG_FLOODFILL; // floodfill 523 } 524 else 525 { 526 if (m_Caps & eExtraBandwidth) 527 caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ 528 else 529 caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth 530 } 531 if (m_Caps & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden 532 if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable 533 if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable 534 535 SetProperty ("caps", caps); 536 } 537 WriteToStream(std::ostream & s) const538 void RouterInfo::WriteToStream (std::ostream& s) const 539 { 540 uint64_t ts = htobe64 (m_Timestamp); 541 s.write ((const char *)&ts, sizeof (ts)); 542 543 // addresses 544 uint8_t numAddresses = m_Addresses->size (); 545 s.write ((char *)&numAddresses, sizeof (numAddresses)); 546 for (const auto& addr_ptr : *m_Addresses) 547 { 548 const Address& address = *addr_ptr; 549 // calculate cost 550 uint8_t cost = 0x7f; 551 if (address.transportStyle == eTransportNTCP) 552 cost = address.published ? COST_NTCP2_PUBLISHED : COST_NTCP2_NON_PUBLISHED; 553 else if (address.transportStyle == eTransportSSU) 554 cost = address.published ? COST_SSU_DIRECT : COST_SSU_THROUGH_INTRODUCERS; 555 s.write ((const char *)&cost, sizeof (cost)); 556 s.write ((const char *)&address.date, sizeof (address.date)); 557 std::stringstream properties; 558 bool isPublished = false; 559 if (address.transportStyle == eTransportNTCP) 560 { 561 if (address.IsNTCP2 ()) 562 { 563 WriteString ("NTCP2", s); 564 if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port) 565 isPublished = true; 566 else 567 { 568 WriteString ("caps", properties); 569 properties << '='; 570 std::string caps; 571 if (address.IsV4 ()) caps += CAPS_FLAG_V4; 572 if (address.IsV6 ()) caps += CAPS_FLAG_V6; 573 if (caps.empty ()) caps += CAPS_FLAG_V4; 574 WriteString (caps, properties); 575 properties << ';'; 576 } 577 } 578 else 579 continue; // don't write NTCP address 580 } 581 else if (address.transportStyle == eTransportSSU) 582 { 583 WriteString ("SSU", s); 584 // caps 585 WriteString ("caps", properties); 586 properties << '='; 587 std::string caps; 588 if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING; 589 if (address.host.is_v4 ()) 590 { 591 if (address.published) 592 { 593 isPublished = true; 594 if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; 595 } 596 else 597 caps += CAPS_FLAG_V4; 598 } 599 else if (address.host.is_v6 ()) 600 { 601 if (address.published) 602 { 603 isPublished = true; 604 if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; 605 } 606 else 607 caps += CAPS_FLAG_V6; 608 } 609 else 610 { 611 if (address.IsV4 ()) caps += CAPS_FLAG_V4; 612 if (address.IsV6 ()) caps += CAPS_FLAG_V6; 613 if (caps.empty ()) caps += CAPS_FLAG_V4; 614 } 615 WriteString (caps, properties); 616 properties << ';'; 617 } 618 else 619 WriteString ("", s); 620 621 if (isPublished) 622 { 623 WriteString ("host", properties); 624 properties << '='; 625 WriteString (address.host.to_string (), properties); 626 properties << ';'; 627 } 628 if (address.transportStyle == eTransportSSU) 629 { 630 // write introducers if any 631 if (!address.ssu->introducers.empty()) 632 { 633 int i = 0; 634 for (const auto& introducer: address.ssu->introducers) 635 { 636 if (introducer.iExp) // expiration is specified 637 { 638 WriteString ("iexp" + boost::lexical_cast<std::string>(i), properties); 639 properties << '='; 640 WriteString (boost::lexical_cast<std::string>(introducer.iExp), properties); 641 properties << ';'; 642 } 643 i++; 644 } 645 i = 0; 646 for (const auto& introducer: address.ssu->introducers) 647 { 648 WriteString ("ihost" + boost::lexical_cast<std::string>(i), properties); 649 properties << '='; 650 WriteString (introducer.iHost.to_string (), properties); 651 properties << ';'; 652 i++; 653 } 654 i = 0; 655 for (const auto& introducer: address.ssu->introducers) 656 { 657 WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties); 658 properties << '='; 659 char value[64]; 660 size_t l = ByteStreamToBase64 (introducer.iKey, 32, value, 64); 661 value[l] = 0; 662 WriteString (value, properties); 663 properties << ';'; 664 i++; 665 } 666 i = 0; 667 for (const auto& introducer: address.ssu->introducers) 668 { 669 WriteString ("iport" + boost::lexical_cast<std::string>(i), properties); 670 properties << '='; 671 WriteString (boost::lexical_cast<std::string>(introducer.iPort), properties); 672 properties << ';'; 673 i++; 674 } 675 i = 0; 676 for (const auto& introducer: address.ssu->introducers) 677 { 678 WriteString ("itag" + boost::lexical_cast<std::string>(i), properties); 679 properties << '='; 680 WriteString (boost::lexical_cast<std::string>(introducer.iTag), properties); 681 properties << ';'; 682 i++; 683 } 684 } 685 // write intro key 686 WriteString ("key", properties); 687 properties << '='; 688 char value[64]; 689 size_t l = ByteStreamToBase64 (address.ssu->key, 32, value, 64); 690 value[l] = 0; 691 WriteString (value, properties); 692 properties << ';'; 693 // write mtu 694 if (address.ssu->mtu) 695 { 696 WriteString ("mtu", properties); 697 properties << '='; 698 WriteString (boost::lexical_cast<std::string>(address.ssu->mtu), properties); 699 properties << ';'; 700 } 701 } 702 703 if (address.IsNTCP2 () && isPublished) 704 { 705 // publish i for NTCP2 706 WriteString ("i", properties); properties << '='; 707 WriteString (address.ntcp2->iv.ToBase64 (), properties); properties << ';'; 708 } 709 710 if (isPublished || address.ssu) 711 { 712 WriteString ("port", properties); 713 properties << '='; 714 WriteString (boost::lexical_cast<std::string>(address.port), properties); 715 properties << ';'; 716 } 717 if (address.IsNTCP2 ()) 718 { 719 // publish s and v for NTCP2 720 WriteString ("s", properties); properties << '='; 721 WriteString (address.ntcp2->staticKey.ToBase64 (), properties); properties << ';'; 722 WriteString ("v", properties); properties << '='; 723 WriteString ("2", properties); properties << ';'; 724 } 725 726 uint16_t size = htobe16 (properties.str ().size ()); 727 s.write ((char *)&size, sizeof (size)); 728 s.write (properties.str ().c_str (), properties.str ().size ()); 729 } 730 731 // peers 732 uint8_t numPeers = 0; 733 s.write ((char *)&numPeers, sizeof (numPeers)); 734 735 // properties 736 std::stringstream properties; 737 for (const auto& p : m_Properties) 738 { 739 WriteString (p.first, properties); 740 properties << '='; 741 WriteString (p.second, properties); 742 properties << ';'; 743 } 744 uint16_t size = htobe16 (properties.str ().size ()); 745 s.write ((char *)&size, sizeof (size)); 746 s.write (properties.str ().c_str (), properties.str ().size ()); 747 } 748 IsNewer(const uint8_t * buf,size_t len) const749 bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const 750 { 751 if (!m_RouterIdentity) return false; 752 size_t size = m_RouterIdentity->GetFullLen (); 753 if (size + 8 > len) return false; 754 return bufbe64toh (buf + size) > m_Timestamp; 755 } 756 LoadBuffer(const std::string & fullPath)757 const uint8_t * RouterInfo::LoadBuffer (const std::string& fullPath) 758 { 759 if (!m_Buffer) 760 { 761 if (LoadFile (fullPath)) 762 LogPrint (eLogDebug, "RouterInfo: Buffer for ", GetIdentHashAbbreviation (GetIdentHash ()), " loaded from file"); 763 } 764 return m_Buffer; 765 } 766 CreateBuffer(const PrivateKeys & privateKeys)767 void RouterInfo::CreateBuffer (const PrivateKeys& privateKeys) 768 { 769 m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); // refresh timstamp 770 std::stringstream s; 771 uint8_t ident[1024]; 772 auto identLen = privateKeys.GetPublic ()->ToBuffer (ident, 1024); 773 auto signatureLen = privateKeys.GetPublic ()->GetSignatureLen (); 774 s.write ((char *)ident, identLen); 775 WriteToStream (s); 776 m_BufferLen = s.str ().size (); 777 if (!m_Buffer) 778 m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; 779 if (m_BufferLen + signatureLen < MAX_RI_BUFFER_SIZE) 780 { 781 memcpy (m_Buffer, s.str ().c_str (), m_BufferLen); 782 // signature 783 privateKeys.Sign ((uint8_t *)m_Buffer, m_BufferLen, (uint8_t *)m_Buffer + m_BufferLen); 784 m_BufferLen += signatureLen; 785 } 786 else 787 LogPrint (eLogError, "RouterInfo: Our RouterInfo is too long ", m_BufferLen + signatureLen); 788 } 789 SaveToFile(const std::string & fullPath)790 bool RouterInfo::SaveToFile (const std::string& fullPath) 791 { 792 if (!m_Buffer) 793 { 794 LogPrint (eLogError, "RouterInfo: Can't save, m_Buffer == NULL"); 795 return false; 796 } 797 std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); 798 if (!f.is_open ()) { 799 LogPrint(eLogError, "RouterInfo: Can't save to ", fullPath); 800 return false; 801 } 802 f.write ((char *)m_Buffer, m_BufferLen); 803 return true; 804 } 805 ReadString(char * str,size_t len,std::istream & s) const806 size_t RouterInfo::ReadString (char * str, size_t len, std::istream& s) const 807 { 808 uint8_t l; 809 s.read ((char *)&l, 1); 810 if (l < len) 811 { 812 s.read (str, l); 813 if (!s) l = 0; // failed, return empty string 814 str[l] = 0; 815 } 816 else 817 { 818 LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len); 819 s.seekg (l, std::ios::cur); // skip 820 str[0] = 0; 821 } 822 return l+1; 823 } 824 WriteString(const std::string & str,std::ostream & s) const825 void RouterInfo::WriteString (const std::string& str, std::ostream& s) const 826 { 827 uint8_t len = str.size (); 828 s.write ((char *)&len, 1); 829 s.write (str.c_str (), len); 830 } 831 AddSSUAddress(const char * host,int port,const uint8_t * key,int mtu)832 void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu) 833 { 834 auto addr = std::make_shared<Address>(); 835 addr->host = boost::asio::ip::address::from_string (host); 836 addr->port = port; 837 addr->transportStyle = eTransportSSU; 838 addr->published = true; 839 addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; 840 addr->date = 0; 841 addr->ssu.reset (new SSUExt ()); 842 addr->ssu->mtu = mtu; 843 if (key) 844 memcpy (addr->ssu->key, key, 32); 845 else 846 RAND_bytes (addr->ssu->key, 32); 847 for (const auto& it: *m_Addresses) // don't insert same address twice 848 if (*it == *addr) return; 849 m_SupportedTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4; 850 m_ReachableTransports |= addr->host.is_v6 () ? eSSUV6 : eSSUV4; 851 m_Addresses->push_back(std::move(addr)); 852 } 853 AddNTCP2Address(const uint8_t * staticKey,const uint8_t * iv,const boost::asio::ip::address & host,int port,uint8_t caps)854 void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, 855 const boost::asio::ip::address& host, int port, uint8_t caps) 856 { 857 auto addr = std::make_shared<Address>(); 858 addr->host = host; 859 addr->port = port; 860 addr->transportStyle = eTransportNTCP; 861 addr->caps = caps; 862 addr->date = 0; 863 addr->ntcp2.reset (new NTCP2Ext ()); 864 if (port) addr->published = true; 865 memcpy (addr->ntcp2->staticKey, staticKey, 32); 866 memcpy (addr->ntcp2->iv, iv, 16); 867 if (addr->IsV4 ()) 868 { 869 m_SupportedTransports |= eNTCP2V4; 870 if (addr->published) m_ReachableTransports |= eNTCP2V4; 871 } 872 if (addr->IsV6 ()) 873 { 874 m_SupportedTransports |= eNTCP2V6; 875 if (addr->published) m_ReachableTransports |= eNTCP2V6; 876 } 877 m_Addresses->push_back(std::move(addr)); 878 } 879 AddIntroducer(const Introducer & introducer)880 bool RouterInfo::AddIntroducer (const Introducer& introducer) 881 { 882 for (auto& addr : *m_Addresses) 883 { 884 if (addr->transportStyle == eTransportSSU && 885 ((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ()))) 886 { 887 for (auto& intro: addr->ssu->introducers) 888 if (intro.iTag == introducer.iTag) return false; // already presented 889 addr->ssu->introducers.push_back (introducer); 890 m_ReachableTransports |= (addr->IsV4 () ? eSSUV4 : eSSUV6); 891 return true; 892 } 893 } 894 return false; 895 } 896 RemoveIntroducer(const boost::asio::ip::udp::endpoint & e)897 bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e) 898 { 899 for (auto& addr: *m_Addresses) 900 { 901 if (addr->transportStyle == eTransportSSU && 902 ((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ()))) 903 { 904 for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) 905 if (boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e) 906 { 907 addr->ssu->introducers.erase (it); 908 if (addr->ssu->introducers.empty ()) 909 m_ReachableTransports &= ~(addr->IsV4 () ? eSSUV4 : eSSUV6); 910 return true; 911 } 912 } 913 } 914 return false; 915 } 916 SetCaps(uint8_t caps)917 void RouterInfo::SetCaps (uint8_t caps) 918 { 919 m_Caps = caps; 920 UpdateCapsProperty (); 921 } 922 SetCaps(const char * caps)923 void RouterInfo::SetCaps (const char * caps) 924 { 925 SetProperty ("caps", caps); 926 m_Caps = 0; 927 ExtractCaps (caps); 928 } 929 SetProperty(const std::string & key,const std::string & value)930 void RouterInfo::SetProperty (const std::string& key, const std::string& value) 931 { 932 m_Properties[key] = value; 933 } 934 DeleteProperty(const std::string & key)935 void RouterInfo::DeleteProperty (const std::string& key) 936 { 937 m_Properties.erase (key); 938 } 939 GetProperty(const std::string & key) const940 std::string RouterInfo::GetProperty (const std::string& key) const 941 { 942 auto it = m_Properties.find (key); 943 if (it != m_Properties.end ()) 944 return it->second; 945 return ""; 946 } 947 IsSSU(bool v4only) const948 bool RouterInfo::IsSSU (bool v4only) const 949 { 950 if (v4only) 951 return m_SupportedTransports & eSSUV4; 952 else 953 return m_SupportedTransports & (eSSUV4 | eSSUV6); 954 } 955 IsSSUV6() const956 bool RouterInfo::IsSSUV6 () const 957 { 958 return m_SupportedTransports & eSSUV6; 959 } 960 IsNTCP2(bool v4only) const961 bool RouterInfo::IsNTCP2 (bool v4only) const 962 { 963 if (v4only) 964 return m_SupportedTransports & eNTCP2V4; 965 else 966 return m_SupportedTransports & (eNTCP2V4 | eNTCP2V6); 967 } 968 IsNTCP2V6() const969 bool RouterInfo::IsNTCP2V6 () const 970 { 971 return m_SupportedTransports & eNTCP2V6; 972 } 973 IsV6() const974 bool RouterInfo::IsV6 () const 975 { 976 return m_SupportedTransports & (eSSUV6 | eNTCP2V6); 977 } 978 IsV4() const979 bool RouterInfo::IsV4 () const 980 { 981 return m_SupportedTransports & (eSSUV4 | eNTCP2V4); 982 } 983 IsMesh() const984 bool RouterInfo::IsMesh () const 985 { 986 return m_SupportedTransports & eNTCP2V6Mesh; 987 } 988 EnableV6()989 void RouterInfo::EnableV6 () 990 { 991 if (!IsV6 ()) 992 { 993 uint8_t addressCaps = AddressCaps::eV6; 994 if (IsV4 ()) addressCaps |= AddressCaps::eV4; 995 SetUnreachableAddressesTransportCaps (addressCaps); 996 UpdateSupportedTransports (); 997 } 998 } 999 EnableV4()1000 void RouterInfo::EnableV4 () 1001 { 1002 if (!IsV4 ()) 1003 { 1004 uint8_t addressCaps = AddressCaps::eV4; 1005 if (IsV6 ()) addressCaps |= AddressCaps::eV6; 1006 SetUnreachableAddressesTransportCaps (addressCaps); 1007 UpdateSupportedTransports (); 1008 } 1009 } 1010 1011 DisableV6()1012 void RouterInfo::DisableV6 () 1013 { 1014 if (IsV6 ()) 1015 { 1016 for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) 1017 { 1018 auto addr = *it; 1019 if (addr->IsV6 ()) 1020 { 1021 if (addr->IsV4 ()) 1022 { 1023 addr->caps &= ~AddressCaps::eV6; 1024 ++it; 1025 } 1026 else 1027 it = m_Addresses->erase (it); 1028 } 1029 else 1030 ++it; 1031 } 1032 UpdateSupportedTransports (); 1033 } 1034 } 1035 DisableV4()1036 void RouterInfo::DisableV4 () 1037 { 1038 if (IsV4 ()) 1039 { 1040 for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) 1041 { 1042 auto addr = *it; 1043 if (addr->IsV4 ()) 1044 { 1045 if (addr->IsV6 ()) 1046 { 1047 addr->caps &= ~AddressCaps::eV4; 1048 ++it; 1049 } 1050 else 1051 it = m_Addresses->erase (it); 1052 } 1053 else 1054 ++it; 1055 } 1056 UpdateSupportedTransports (); 1057 } 1058 } 1059 EnableMesh()1060 void RouterInfo::EnableMesh () 1061 { 1062 if (!IsMesh ()) 1063 { 1064 m_SupportedTransports |= eNTCP2V6Mesh; 1065 m_ReachableTransports |= eNTCP2V6Mesh; 1066 } 1067 } 1068 DisableMesh()1069 void RouterInfo::DisableMesh () 1070 { 1071 if (IsMesh ()) 1072 { 1073 m_SupportedTransports &= ~eNTCP2V6Mesh; 1074 m_ReachableTransports &= ~eNTCP2V6Mesh; 1075 for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) 1076 { 1077 auto addr = *it; 1078 if (i2p::util::net::IsYggdrasilAddress (addr->host)) 1079 it = m_Addresses->erase (it); 1080 else 1081 ++it; 1082 } 1083 } 1084 } 1085 GetSSUAddress(bool v4only) const1086 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUAddress (bool v4only) const 1087 { 1088 return GetAddress ( 1089 [v4only](std::shared_ptr<const RouterInfo::Address> address)->bool 1090 { 1091 return (address->transportStyle == eTransportSSU) && (!v4only || address->IsV4 ()); 1092 }); 1093 } 1094 GetSSUV6Address() const1095 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSUV6Address () const 1096 { 1097 return GetAddress ( 1098 [](std::shared_ptr<const RouterInfo::Address> address)->bool 1099 { 1100 return (address->transportStyle == eTransportSSU) && address->IsV6(); 1101 }); 1102 } 1103 1104 template<typename Filter> GetAddress(Filter filter) const1105 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const 1106 { 1107 // TODO: make it more generic using comparator 1108 #if (BOOST_VERSION >= 105300) 1109 auto addresses = boost::atomic_load (&m_Addresses); 1110 #else 1111 auto addresses = m_Addresses; 1112 #endif 1113 for (const auto& address : *addresses) 1114 if (filter (address)) return address; 1115 1116 return nullptr; 1117 } 1118 GetNTCP2AddressWithStaticKey(const uint8_t * key) const1119 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCP2AddressWithStaticKey (const uint8_t * key) const 1120 { 1121 if (!key) return nullptr; 1122 return GetAddress ( 1123 [key](std::shared_ptr<const RouterInfo::Address> address)->bool 1124 { 1125 return address->IsNTCP2 () && !memcmp (address->ntcp2->staticKey, key, 32); 1126 }); 1127 } 1128 GetPublishedNTCP2V4Address() const1129 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const 1130 { 1131 return GetAddress ( 1132 [](std::shared_ptr<const RouterInfo::Address> address)->bool 1133 { 1134 return address->IsPublishedNTCP2 () && address->host.is_v4 (); 1135 }); 1136 } 1137 GetPublishedNTCP2V6Address() const1138 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const 1139 { 1140 return GetAddress ( 1141 [](std::shared_ptr<const RouterInfo::Address> address)->bool 1142 { 1143 return address->IsPublishedNTCP2 () && address->host.is_v6 () && 1144 !i2p::util::net::IsYggdrasilAddress (address->host); 1145 }); 1146 } 1147 GetYggdrasilAddress() const1148 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const 1149 { 1150 return GetAddress ( 1151 [](std::shared_ptr<const RouterInfo::Address> address)->bool 1152 { 1153 return address->IsPublishedNTCP2 () && i2p::util::net::IsYggdrasilAddress (address->host); 1154 }); 1155 } 1156 GetProfile() const1157 std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const 1158 { 1159 if (!m_Profile) 1160 m_Profile = GetRouterProfile (GetIdentHash ()); 1161 return m_Profile; 1162 } 1163 Encrypt(const uint8_t * data,uint8_t * encrypted) const1164 void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted) const 1165 { 1166 auto encryptor = m_RouterIdentity->CreateEncryptor (nullptr); 1167 if (encryptor) 1168 encryptor->Encrypt (data, encrypted); 1169 } 1170 IsEligibleFloodfill() const1171 bool RouterInfo::IsEligibleFloodfill () const 1172 { 1173 // floodfill must be reachable by ipv4, >= 0.9.38 and not DSA 1174 return IsReachableBy (eNTCP2V4 | eSSUV4) && m_Version >= NETDB_MIN_FLOODFILL_VERSION && 1175 GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; 1176 } 1177 IsPeerTesting(bool v4) const1178 bool RouterInfo::IsPeerTesting (bool v4) const 1179 { 1180 if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; 1181 return (bool)GetAddress ( 1182 [v4](std::shared_ptr<const RouterInfo::Address> address)->bool 1183 { 1184 return (address->transportStyle == eTransportSSU) && address->IsPeerTesting () && 1185 ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU (); 1186 }); 1187 } 1188 IsIntroducer(bool v4) const1189 bool RouterInfo::IsIntroducer (bool v4) const 1190 { 1191 if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false; 1192 return (bool)GetAddress ( 1193 [v4](std::shared_ptr<const RouterInfo::Address> address)->bool 1194 { 1195 return (address->transportStyle == eTransportSSU) && address->IsIntroducer () && 1196 ((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified (); 1197 }); 1198 } 1199 SetUnreachableAddressesTransportCaps(uint8_t transports)1200 void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) 1201 { 1202 for (auto& addr: *m_Addresses) 1203 { 1204 // TODO: implement SSU 1205 if (addr->transportStyle == eTransportNTCP && !addr->IsPublishedNTCP2 ()) 1206 { 1207 addr->caps &= ~(eV4 | eV6); 1208 addr->caps |= transports; 1209 } 1210 } 1211 } 1212 UpdateSupportedTransports()1213 void RouterInfo::UpdateSupportedTransports () 1214 { 1215 m_SupportedTransports = 0; 1216 m_ReachableTransports = 0; 1217 for (const auto& addr: *m_Addresses) 1218 { 1219 uint8_t transports = 0; 1220 if (addr->transportStyle == eTransportNTCP) 1221 { 1222 if (addr->IsV4 ()) transports |= eNTCP2V4; 1223 if (addr->IsV6 ()) 1224 transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6); 1225 if (addr->IsPublishedNTCP2 ()) 1226 m_ReachableTransports |= transports; 1227 } 1228 else if (addr->transportStyle == eTransportSSU) 1229 { 1230 if (addr->IsV4 ()) transports |= eSSUV4; 1231 if (addr->IsV6 ()) transports |= eSSUV6; 1232 if (addr->IsReachableSSU ()) 1233 m_ReachableTransports |= transports; 1234 } 1235 m_SupportedTransports |= transports; 1236 } 1237 } 1238 } 1239 } 1240