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 10 #include <openssl/rand.h> 11 #include <openssl/sha.h> 12 #include <openssl/hmac.h> 13 #include <stdlib.h> 14 #include <vector> 15 #include "Log.h" 16 #include "I2PEndian.h" 17 #include "Crypto.h" 18 #include "Siphash.h" 19 #include "RouterContext.h" 20 #include "Transports.h" 21 #include "NetDb.hpp" 22 #include "NTCP2.h" 23 #include "HTTP.h" 24 #include "util.h" 25 26 #ifdef __linux__ 27 #include <linux/in6.h> 28 #endif 29 30 namespace i2p 31 { 32 namespace transport 33 { NTCP2Establisher()34 NTCP2Establisher::NTCP2Establisher (): 35 m_SessionConfirmedBuffer (nullptr) 36 { 37 } 38 ~NTCP2Establisher()39 NTCP2Establisher::~NTCP2Establisher () 40 { 41 delete[] m_SessionConfirmedBuffer; 42 } 43 KeyDerivationFunction1(const uint8_t * pub,i2p::crypto::X25519Keys & priv,const uint8_t * rs,const uint8_t * epub)44 void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub) 45 { 46 i2p::crypto::InitNoiseXKState (*this, rs); 47 // h = SHA256(h || epub) 48 MixHash (epub, 32); 49 // x25519 between pub and priv 50 uint8_t inputKeyMaterial[32]; 51 priv.Agree (pub, inputKeyMaterial); 52 MixKey (inputKeyMaterial); 53 } 54 KDF1Alice()55 void NTCP2Establisher::KDF1Alice () 56 { 57 KeyDerivationFunction1 (m_RemoteStaticKey, *m_EphemeralKeys, m_RemoteStaticKey, GetPub ()); 58 } 59 KDF1Bob()60 void NTCP2Establisher::KDF1Bob () 61 { 62 KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ()); 63 } 64 KeyDerivationFunction2(const uint8_t * sessionRequest,size_t sessionRequestLen,const uint8_t * epub)65 void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub) 66 { 67 MixHash (sessionRequest + 32, 32); // encrypted payload 68 69 int paddingLength = sessionRequestLen - 64; 70 if (paddingLength > 0) 71 MixHash (sessionRequest + 64, paddingLength); 72 MixHash (epub, 32); 73 74 // x25519 between remote pub and ephemaral priv 75 uint8_t inputKeyMaterial[32]; 76 m_EphemeralKeys->Agree (GetRemotePub (), inputKeyMaterial); 77 78 MixKey (inputKeyMaterial); 79 } 80 KDF2Alice()81 void NTCP2Establisher::KDF2Alice () 82 { 83 KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetRemotePub ()); 84 } 85 KDF2Bob()86 void NTCP2Establisher::KDF2Bob () 87 { 88 KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ()); 89 } 90 KDF3Alice()91 void NTCP2Establisher::KDF3Alice () 92 { 93 uint8_t inputKeyMaterial[32]; 94 i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial); 95 MixKey (inputKeyMaterial); 96 } 97 KDF3Bob()98 void NTCP2Establisher::KDF3Bob () 99 { 100 uint8_t inputKeyMaterial[32]; 101 m_EphemeralKeys->Agree (m_RemoteStaticKey, inputKeyMaterial); 102 MixKey (inputKeyMaterial); 103 } 104 CreateEphemeralKey()105 void NTCP2Establisher::CreateEphemeralKey () 106 { 107 m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair (); 108 } 109 CreateSessionRequestMessage()110 void NTCP2Establisher::CreateSessionRequestMessage () 111 { 112 // create buffer and fill padding 113 auto paddingLength = rand () % (NTCP2_SESSION_REQUEST_MAX_SIZE - 64); // message length doesn't exceed 287 bytes 114 m_SessionRequestBufferLen = paddingLength + 64; 115 RAND_bytes (m_SessionRequestBuffer + 64, paddingLength); 116 // encrypt X 117 i2p::crypto::CBCEncryption encryption; 118 encryption.SetKey (m_RemoteIdentHash); 119 encryption.SetIV (m_IV); 120 encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X 121 encryption.GetIV (m_IV); // save IV for SessionCreated 122 // encryption key for next block 123 KDF1Alice (); 124 // fill options 125 uint8_t options[32]; // actual options size is 16 bytes 126 memset (options, 0, 16); 127 options[0] = i2p::context.GetNetID (); // network ID 128 options[1] = 2; // ver 129 htobe16buf (options + 2, paddingLength); // padLen 130 // m3p2Len 131 auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen (); 132 m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options 133 htobe16buf (options + 4, m3p2Len); 134 // fill m3p2 payload (RouterInfo block) 135 m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes 136 uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; 137 m3p2[0] = eNTCP2BlkRouterInfo; // block 138 htobe16buf (m3p2 + 1, bufLen + 1); // flag + RI 139 m3p2[3] = 0; // flag 140 memcpy (m3p2 + 4, i2p::context.GetRouterInfo ().GetBuffer (), bufLen); // TODO: own RI should be protected by mutex 141 // 2 bytes reserved 142 htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsA 143 // 4 bytes reserved 144 // sign and encrypt options, use m_H as AD 145 uint8_t nonce[12]; 146 memset (nonce, 0, 12); // set nonce to zero 147 i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt 148 } 149 CreateSessionCreatedMessage()150 void NTCP2Establisher::CreateSessionCreatedMessage () 151 { 152 auto paddingLen = rand () % (NTCP2_SESSION_CREATED_MAX_SIZE - 64); 153 m_SessionCreatedBufferLen = paddingLen + 64; 154 RAND_bytes (m_SessionCreatedBuffer + 64, paddingLen); 155 // encrypt Y 156 i2p::crypto::CBCEncryption encryption; 157 encryption.SetKey (i2p::context.GetIdentHash ()); 158 encryption.SetIV (m_IV); 159 encryption.Encrypt (GetPub (), 32, m_SessionCreatedBuffer); // Y 160 // encryption key for next block (m_K) 161 KDF2Bob (); 162 uint8_t options[16]; 163 memset (options, 0, 16); 164 htobe16buf (options + 2, paddingLen); // padLen 165 htobe32buf (options + 8, i2p::util::GetSecondsSinceEpoch ()); // tsB 166 // sign and encrypt options, use m_H as AD 167 uint8_t nonce[12]; 168 memset (nonce, 0, 12); // set nonce to zero 169 i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt 170 171 } 172 CreateSessionConfirmedMessagePart1(const uint8_t * nonce)173 void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce) 174 { 175 // update AD 176 MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload 177 int paddingLength = m_SessionCreatedBufferLen - 64; 178 if (paddingLength > 0) 179 MixHash (m_SessionCreatedBuffer + 64, paddingLength); 180 181 // part1 48 bytes 182 i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt 183 } 184 CreateSessionConfirmedMessagePart2(const uint8_t * nonce)185 void NTCP2Establisher::CreateSessionConfirmedMessagePart2 (const uint8_t * nonce) 186 { 187 // part 2 188 // update AD again 189 MixHash (m_SessionConfirmedBuffer, 48); 190 // encrypt m3p2, it must be filled in SessionRequest 191 KDF3Alice (); 192 uint8_t * m3p2 = m_SessionConfirmedBuffer + 48; 193 i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt 194 // update h again 195 MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext) 196 } 197 ProcessSessionRequestMessage(uint16_t & paddingLen)198 bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen) 199 { 200 // decrypt X 201 i2p::crypto::CBCDecryption decryption; 202 decryption.SetKey (i2p::context.GetIdentHash ()); 203 decryption.SetIV (i2p::context.GetNTCP2IV ()); 204 decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ()); 205 decryption.GetIV (m_IV); // save IV for SessionCreated 206 // decryption key for next block 207 KDF1Bob (); 208 // verify MAC and decrypt options block (32 bytes), use m_H as AD 209 uint8_t nonce[12], options[16]; 210 memset (nonce, 0, 12); // set nonce to zero 211 if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, GetH (), 32, GetK (), nonce, options, 16, false)) // decrypt 212 { 213 // options 214 if (options[0] && options[0] != i2p::context.GetNetID ()) 215 { 216 LogPrint (eLogWarning, "NTCP2: SessionRequest networkID ", (int)options[0], " mismatch. Expected ", i2p::context.GetNetID ()); 217 return false; 218 } 219 if (options[1] == 2) // ver is always 2 220 { 221 paddingLen = bufbe16toh (options + 2); 222 m_SessionRequestBufferLen = paddingLen + 64; 223 m3p2Len = bufbe16toh (options + 4); 224 if (m3p2Len < 16) 225 { 226 LogPrint (eLogWarning, "NTCP2: SessionRequest m3p2len=", m3p2Len, " is too short"); 227 return false; 228 } 229 // check timestamp 230 auto ts = i2p::util::GetSecondsSinceEpoch (); 231 uint32_t tsA = bufbe32toh (options + 8); 232 if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW) 233 { 234 LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew"); 235 return false; 236 } 237 } 238 else 239 { 240 LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]); 241 return false; 242 } 243 } 244 else 245 { 246 LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed "); 247 return false; 248 } 249 return true; 250 } 251 ProcessSessionCreatedMessage(uint16_t & paddingLen)252 bool NTCP2Establisher::ProcessSessionCreatedMessage (uint16_t& paddingLen) 253 { 254 m_SessionCreatedBufferLen = 64; 255 // decrypt Y 256 i2p::crypto::CBCDecryption decryption; 257 decryption.SetKey (m_RemoteIdentHash); 258 decryption.SetIV (m_IV); 259 decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ()); 260 // decryption key for next block (m_K) 261 KDF2Alice (); 262 // decrypt and verify MAC 263 uint8_t payload[16]; 264 uint8_t nonce[12]; 265 memset (nonce, 0, 12); // set nonce to zero 266 if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, GetH (), 32, GetK (), nonce, payload, 16, false)) // decrypt 267 { 268 // options 269 paddingLen = bufbe16toh(payload + 2); 270 // check timestamp 271 auto ts = i2p::util::GetSecondsSinceEpoch (); 272 uint32_t tsB = bufbe32toh (payload + 8); 273 if (tsB < ts - NTCP2_CLOCK_SKEW || tsB > ts + NTCP2_CLOCK_SKEW) 274 { 275 LogPrint (eLogWarning, "NTCP2: SessionCreated time difference ", (int)(ts - tsB), " exceeds clock skew"); 276 return false; 277 } 278 } 279 else 280 { 281 LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed "); 282 return false; 283 } 284 return true; 285 } 286 ProcessSessionConfirmedMessagePart1(const uint8_t * nonce)287 bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce) 288 { 289 // update AD 290 MixHash (m_SessionCreatedBuffer + 32, 32); // encrypted payload 291 int paddingLength = m_SessionCreatedBufferLen - 64; 292 if (paddingLength > 0) 293 MixHash (m_SessionCreatedBuffer + 64, paddingLength); 294 295 if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, GetH (), 32, GetK (), nonce, m_RemoteStaticKey, 32, false)) // decrypt S 296 { 297 LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); 298 return false; 299 } 300 return true; 301 } 302 ProcessSessionConfirmedMessagePart2(const uint8_t * nonce,uint8_t * m3p2Buf)303 bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf) 304 { 305 // update AD again 306 MixHash (m_SessionConfirmedBuffer, 48); 307 308 KDF3Bob (); 309 if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt 310 // caclulate new h again for KDF data 311 MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext) 312 else 313 { 314 LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed "); 315 return false; 316 } 317 return true; 318 } 319 NTCP2Session(NTCP2Server & server,std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter,std::shared_ptr<const i2p::data::RouterInfo::Address> addr)320 NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter, 321 std::shared_ptr<const i2p::data::RouterInfo::Address> addr): 322 TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT), 323 m_Server (server), m_Socket (m_Server.GetService ()), 324 m_IsEstablished (false), m_IsTerminated (false), 325 m_Establisher (new NTCP2Establisher), 326 #if OPENSSL_SIPHASH 327 m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr), 328 #else 329 m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr), 330 #endif 331 m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr), 332 m_NextReceivedBufferSize (0), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0), 333 m_IsSending (false), m_IsReceiving (false), m_NextPaddingSize (16) 334 { 335 if (in_RemoteRouter) // Alice 336 { 337 m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash (); 338 if (addr) 339 { 340 memcpy (m_Establisher->m_RemoteStaticKey, addr->ntcp2->staticKey, 32); 341 memcpy (m_Establisher->m_IV, addr->ntcp2->iv, 16); 342 m_RemoteEndpoint = boost::asio::ip::tcp::endpoint (addr->host, addr->port); 343 } 344 else 345 LogPrint (eLogWarning, "NTCP2: Missing NTCP2 address"); 346 } 347 m_NextRouterInfoResendTime = i2p::util::GetSecondsSinceEpoch () + NTCP2_ROUTERINFO_RESEND_INTERVAL + 348 rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; 349 } 350 ~NTCP2Session()351 NTCP2Session::~NTCP2Session () 352 { 353 delete[] m_NextReceivedBuffer; 354 delete[] m_NextSendBuffer; 355 #if OPENSSL_SIPHASH 356 if (m_SendMDCtx) EVP_MD_CTX_destroy (m_SendMDCtx); 357 if (m_ReceiveMDCtx) EVP_MD_CTX_destroy (m_ReceiveMDCtx); 358 #endif 359 } 360 Terminate()361 void NTCP2Session::Terminate () 362 { 363 if (!m_IsTerminated) 364 { 365 m_IsTerminated = true; 366 m_IsEstablished = false; 367 boost::system::error_code ec; 368 m_Socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); 369 if (ec) 370 LogPrint (eLogDebug, "NTCP2: Couldn't shutdown socket: ", ec.message ()); 371 m_Socket.close (); 372 transports.PeerDisconnected (shared_from_this ()); 373 m_Server.RemoveNTCP2Session (shared_from_this ()); 374 m_SendQueue.clear (); 375 LogPrint (eLogDebug, "NTCP2: Session terminated"); 376 } 377 } 378 TerminateByTimeout()379 void NTCP2Session::TerminateByTimeout () 380 { 381 SendTerminationAndTerminate (eNTCP2IdleTimeout); 382 } 383 Done()384 void NTCP2Session::Done () 385 { 386 m_Server.GetService ().post (std::bind (&NTCP2Session::Terminate, shared_from_this ())); 387 } 388 Established()389 void NTCP2Session::Established () 390 { 391 m_IsEstablished = true; 392 m_Establisher.reset (nullptr); 393 SetTerminationTimeout (NTCP2_TERMINATION_TIMEOUT); 394 transports.PeerConnected (shared_from_this ()); 395 } 396 CreateNonce(uint64_t seqn,uint8_t * nonce)397 void NTCP2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) 398 { 399 memset (nonce, 0, 4); 400 htole64buf (nonce + 4, seqn); 401 } 402 CreateNextReceivedBuffer(size_t size)403 void NTCP2Session::CreateNextReceivedBuffer (size_t size) 404 { 405 if (m_NextReceivedBuffer) 406 { 407 if (size <= m_NextReceivedBufferSize) 408 return; // buffer is good, do nothing 409 else 410 delete[] m_NextReceivedBuffer; 411 } 412 m_NextReceivedBuffer = new uint8_t[size]; 413 m_NextReceivedBufferSize = size; 414 } 415 DeleteNextReceiveBuffer(uint64_t ts)416 void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts) 417 { 418 if (m_NextReceivedBuffer && !m_IsReceiving && 419 ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT) 420 { 421 delete[] m_NextReceivedBuffer; 422 m_NextReceivedBuffer = nullptr; 423 m_NextReceivedBufferSize = 0; 424 } 425 } 426 KeyDerivationFunctionDataPhase()427 void NTCP2Session::KeyDerivationFunctionDataPhase () 428 { 429 uint8_t k[64]; 430 i2p::crypto::HKDF (m_Establisher->GetCK (), nullptr, 0, "", k); // k_ab, k_ba = HKDF(ck, zerolen) 431 memcpy (m_Kab, k, 32); memcpy (m_Kba, k + 32, 32); 432 uint8_t master[32]; 433 i2p::crypto::HKDF (m_Establisher->GetCK (), nullptr, 0, "ask", master, 32); // ask_master = HKDF(ck, zerolen, info="ask") 434 uint8_t h[39]; 435 memcpy (h, m_Establisher->GetH (), 32); 436 memcpy (h + 32, "siphash", 7); 437 i2p::crypto::HKDF (master, h, 39, "", master, 32); // sip_master = HKDF(ask_master, h || "siphash") 438 i2p::crypto::HKDF (master, nullptr, 0, "", k); // sipkeys_ab, sipkeys_ba = HKDF(sip_master, zerolen) 439 memcpy (m_Sipkeysab, k, 32); memcpy (m_Sipkeysba, k + 32, 32); 440 } 441 442 SendSessionRequest()443 void NTCP2Session::SendSessionRequest () 444 { 445 m_Establisher->CreateSessionRequestMessage (); 446 // send message 447 boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionRequestBuffer, m_Establisher->m_SessionRequestBufferLen), boost::asio::transfer_all (), 448 std::bind(&NTCP2Session::HandleSessionRequestSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 449 } 450 HandleSessionRequestSent(const boost::system::error_code & ecode,std::size_t bytes_transferred)451 void NTCP2Session::HandleSessionRequestSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) 452 { 453 (void) bytes_transferred; 454 if (ecode) 455 { 456 LogPrint (eLogWarning, "NTCP2: Couldn't send SessionRequest message: ", ecode.message ()); 457 Terminate (); 458 } 459 else 460 { 461 // we receive first 64 bytes (32 Y, and 32 ChaCha/Poly frame) first 462 boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionCreatedBuffer, 64), boost::asio::transfer_all (), 463 std::bind(&NTCP2Session::HandleSessionCreatedReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 464 } 465 } 466 HandleSessionRequestReceived(const boost::system::error_code & ecode,std::size_t bytes_transferred)467 void NTCP2Session::HandleSessionRequestReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) 468 { 469 (void) bytes_transferred; 470 if (ecode) 471 { 472 LogPrint (eLogWarning, "NTCP2: SessionRequest read error: ", ecode.message ()); 473 Terminate (); 474 } 475 else 476 { 477 LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred); 478 uint16_t paddingLen = 0; 479 if (m_Establisher->ProcessSessionRequestMessage (paddingLen)) 480 { 481 if (paddingLen > 0) 482 { 483 if (paddingLen <= NTCP2_SESSION_REQUEST_MAX_SIZE - 64) // session request is 287 bytes max 484 { 485 boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (), 486 std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 487 } 488 else 489 { 490 LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long"); 491 Terminate (); 492 } 493 } 494 else 495 SendSessionCreated (); 496 } 497 else 498 Terminate (); 499 } 500 } 501 HandleSessionRequestPaddingReceived(const boost::system::error_code & ecode,std::size_t bytes_transferred)502 void NTCP2Session::HandleSessionRequestPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) 503 { 504 if (ecode) 505 { 506 LogPrint (eLogWarning, "NTCP2: SessionRequest padding read error: ", ecode.message ()); 507 Terminate (); 508 } 509 else 510 SendSessionCreated (); 511 } 512 SendSessionCreated()513 void NTCP2Session::SendSessionCreated () 514 { 515 m_Establisher->CreateSessionCreatedMessage (); 516 // send message 517 boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionCreatedBuffer, m_Establisher->m_SessionCreatedBufferLen), boost::asio::transfer_all (), 518 std::bind(&NTCP2Session::HandleSessionCreatedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 519 } 520 HandleSessionCreatedReceived(const boost::system::error_code & ecode,std::size_t bytes_transferred)521 void NTCP2Session::HandleSessionCreatedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) 522 { 523 if (ecode) 524 { 525 LogPrint (eLogWarning, "NTCP2: SessionCreated read error: ", ecode.message ()); 526 Terminate (); 527 } 528 else 529 { 530 LogPrint (eLogDebug, "NTCP2: SessionCreated received ", bytes_transferred); 531 uint16_t paddingLen = 0; 532 if (m_Establisher->ProcessSessionCreatedMessage (paddingLen)) 533 { 534 if (paddingLen > 0) 535 { 536 if (paddingLen <= NTCP2_SESSION_CREATED_MAX_SIZE - 64) // session created is 287 bytes max 537 { 538 boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionCreatedBuffer + 64, paddingLen), boost::asio::transfer_all (), 539 std::bind(&NTCP2Session::HandleSessionCreatedPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 540 } 541 else 542 { 543 LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long"); 544 Terminate (); 545 } 546 } 547 else 548 SendSessionConfirmed (); 549 } 550 else 551 Terminate (); 552 } 553 } 554 HandleSessionCreatedPaddingReceived(const boost::system::error_code & ecode,std::size_t bytes_transferred)555 void NTCP2Session::HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) 556 { 557 if (ecode) 558 { 559 LogPrint (eLogWarning, "NTCP2: SessionCreated padding read error: ", ecode.message ()); 560 Terminate (); 561 } 562 else 563 { 564 m_Establisher->m_SessionCreatedBufferLen += bytes_transferred; 565 SendSessionConfirmed (); 566 } 567 } 568 SendSessionConfirmed()569 void NTCP2Session::SendSessionConfirmed () 570 { 571 uint8_t nonce[12]; 572 CreateNonce (1, nonce); // set nonce to 1 573 m_Establisher->CreateSessionConfirmedMessagePart1 (nonce); 574 memset (nonce, 0, 12); // set nonce back to 0 575 m_Establisher->CreateSessionConfirmedMessagePart2 (nonce); 576 // send message 577 boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (), 578 std::bind(&NTCP2Session::HandleSessionConfirmedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 579 } 580 HandleSessionConfirmedSent(const boost::system::error_code & ecode,std::size_t bytes_transferred)581 void NTCP2Session::HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) 582 { 583 (void) bytes_transferred; 584 if (ecode) 585 { 586 LogPrint (eLogWarning, "NTCP2: Couldn't send SessionConfirmed message: ", ecode.message ()); 587 Terminate (); 588 } 589 else 590 { 591 LogPrint (eLogDebug, "NTCP2: SessionConfirmed sent"); 592 KeyDerivationFunctionDataPhase (); 593 // Alice data phase keys 594 m_SendKey = m_Kab; 595 m_ReceiveKey = m_Kba; 596 SetSipKeys (m_Sipkeysab, m_Sipkeysba); 597 memcpy (m_ReceiveIV.buf, m_Sipkeysba + 16, 8); 598 memcpy (m_SendIV.buf, m_Sipkeysab + 16, 8); 599 Established (); 600 ReceiveLength (); 601 602 // TODO: remove 603 // m_SendQueue.push_back (CreateDeliveryStatusMsg (1)); 604 // SendQueue (); 605 } 606 } 607 HandleSessionCreatedSent(const boost::system::error_code & ecode,std::size_t bytes_transferred)608 void NTCP2Session::HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) 609 { 610 (void) bytes_transferred; 611 if (ecode) 612 { 613 LogPrint (eLogWarning, "NTCP2: Couldn't send SessionCreated message: ", ecode.message ()); 614 Terminate (); 615 } 616 else 617 { 618 LogPrint (eLogDebug, "NTCP2: SessionCreated sent"); 619 m_Establisher->m_SessionConfirmedBuffer = new uint8_t[m_Establisher->m3p2Len + 48]; 620 boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (), 621 std::bind(&NTCP2Session::HandleSessionConfirmedReceived , shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 622 } 623 } 624 HandleSessionConfirmedReceived(const boost::system::error_code & ecode,std::size_t bytes_transferred)625 void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) 626 { 627 if (ecode) 628 { 629 LogPrint (eLogWarning, "NTCP2: SessionConfirmed read error: ", ecode.message ()); 630 Terminate (); 631 } 632 else 633 { 634 LogPrint (eLogDebug, "NTCP2: SessionConfirmed received"); 635 // part 1 636 uint8_t nonce[12]; 637 CreateNonce (1, nonce); 638 if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce)) 639 { 640 // part 2 641 std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC 642 memset (nonce, 0, 12); // set nonce to 0 again 643 if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf.data ())) 644 { 645 KeyDerivationFunctionDataPhase (); 646 // Bob data phase keys 647 m_SendKey = m_Kba; 648 m_ReceiveKey = m_Kab; 649 SetSipKeys (m_Sipkeysba, m_Sipkeysab); 650 memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8); 651 memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8); 652 // payload 653 // process RI 654 if (buf[0] != eNTCP2BlkRouterInfo) 655 { 656 LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)buf[0], " in SessionConfirmed"); 657 Terminate (); 658 return; 659 } 660 auto size = bufbe16toh (buf.data () + 1); 661 if (size > buf.size () - 3) 662 { 663 LogPrint (eLogError, "NTCP2: Unexpected RouterInfo size ", size, " in SessionConfirmed"); 664 Terminate (); 665 return; 666 } 667 // TODO: check flag 668 i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag 669 if (ri.IsUnreachable ()) 670 { 671 LogPrint (eLogError, "NTCP2: Signature verification failed in SessionConfirmed"); 672 SendTerminationAndTerminate (eNTCP2RouterInfoSignatureVerificationFail); 673 return; 674 } 675 if (i2p::util::GetMillisecondsSinceEpoch () > ri.GetTimestamp () + i2p::data::NETDB_MIN_EXPIRATION_TIMEOUT*1000LL) // 90 minutes 676 { 677 LogPrint (eLogError, "NTCP2: RouterInfo is too old in SessionConfirmed"); 678 SendTerminationAndTerminate (eNTCP2Message3Error); 679 return; 680 } 681 auto addr = ri.GetNTCP2AddressWithStaticKey (m_Establisher->m_RemoteStaticKey); 682 if (!addr) 683 { 684 LogPrint (eLogError, "NTCP2: No NTCP2 address with static key found in SessionConfirmed"); 685 Terminate (); 686 return; 687 } 688 i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, buf.data () + 3, size)); // TODO: should insert ri and not parse it twice 689 // TODO: process options 690 691 // ready to communicate 692 auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already 693 SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ()); 694 if (m_Server.AddNTCP2Session (shared_from_this (), true)) 695 { 696 Established (); 697 ReceiveLength (); 698 } 699 else 700 Terminate (); 701 } 702 else 703 Terminate (); 704 } 705 else 706 Terminate (); 707 } 708 } 709 SetSipKeys(const uint8_t * sendSipKey,const uint8_t * receiveSipKey)710 void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey) 711 { 712 #if OPENSSL_SIPHASH 713 EVP_PKEY * sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16); 714 m_SendMDCtx = EVP_MD_CTX_create (); 715 EVP_PKEY_CTX *ctx = nullptr; 716 EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, sipKey); 717 EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr); 718 EVP_PKEY_free (sipKey); 719 720 sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16); 721 m_ReceiveMDCtx = EVP_MD_CTX_create (); 722 ctx = nullptr; 723 EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, sipKey); 724 EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr); 725 EVP_PKEY_free (sipKey); 726 #else 727 m_SendSipKey = sendSipKey; 728 m_ReceiveSipKey = receiveSipKey; 729 #endif 730 } 731 ClientLogin()732 void NTCP2Session::ClientLogin () 733 { 734 m_Establisher->CreateEphemeralKey (); 735 SendSessionRequest (); 736 } 737 ServerLogin()738 void NTCP2Session::ServerLogin () 739 { 740 m_Establisher->CreateEphemeralKey (); 741 boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer, 64), boost::asio::transfer_all (), 742 std::bind(&NTCP2Session::HandleSessionRequestReceived, shared_from_this (), 743 std::placeholders::_1, std::placeholders::_2)); 744 } 745 ReceiveLength()746 void NTCP2Session::ReceiveLength () 747 { 748 if (IsTerminated ()) return; 749 #ifdef __linux__ 750 const int one = 1; 751 setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one)); 752 #endif 753 boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (), 754 std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 755 } 756 HandleReceivedLength(const boost::system::error_code & ecode,std::size_t bytes_transferred)757 void NTCP2Session::HandleReceivedLength (const boost::system::error_code& ecode, std::size_t bytes_transferred) 758 { 759 if (ecode) 760 { 761 if (ecode != boost::asio::error::operation_aborted) 762 LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ()); 763 Terminate (); 764 } 765 else 766 { 767 #if OPENSSL_SIPHASH 768 EVP_DigestSignInit (m_ReceiveMDCtx, nullptr, nullptr, nullptr, nullptr); 769 EVP_DigestSignUpdate (m_ReceiveMDCtx, m_ReceiveIV.buf, 8); 770 size_t l = 8; 771 EVP_DigestSignFinal (m_ReceiveMDCtx, m_ReceiveIV.buf, &l); 772 #else 773 i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey); 774 #endif 775 // m_NextReceivedLen comes from the network in BigEndian 776 m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key); 777 LogPrint (eLogDebug, "NTCP2: Received length ", m_NextReceivedLen); 778 if (m_NextReceivedLen >= 16) 779 { 780 CreateNextReceivedBuffer (m_NextReceivedLen); 781 boost::system::error_code ec; 782 size_t moreBytes = m_Socket.available(ec); 783 if (!ec && moreBytes >= m_NextReceivedLen) 784 { 785 // read and process message immediately if available 786 moreBytes = boost::asio::read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), ec); 787 HandleReceived (ec, moreBytes); 788 } 789 else 790 Receive (); 791 } 792 else 793 { 794 LogPrint (eLogError, "NTCP2: Received length ", m_NextReceivedLen, " is too short"); 795 Terminate (); 796 } 797 } 798 } 799 Receive()800 void NTCP2Session::Receive () 801 { 802 if (IsTerminated ()) return; 803 #ifdef __linux__ 804 const int one = 1; 805 setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one)); 806 #endif 807 m_IsReceiving = true; 808 boost::asio::async_read (m_Socket, boost::asio::buffer(m_NextReceivedBuffer, m_NextReceivedLen), boost::asio::transfer_all (), 809 std::bind(&NTCP2Session::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 810 } 811 HandleReceived(const boost::system::error_code & ecode,std::size_t bytes_transferred)812 void NTCP2Session::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) 813 { 814 if (ecode) 815 { 816 if (ecode != boost::asio::error::operation_aborted) 817 LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ()); 818 Terminate (); 819 } 820 else 821 { 822 m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); 823 m_NumReceivedBytes += bytes_transferred + 2; // + length 824 i2p::transport::transports.UpdateReceivedBytes (bytes_transferred); 825 uint8_t nonce[12]; 826 CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++; 827 if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false)) 828 { 829 LogPrint (eLogDebug, "NTCP2: Received message decrypted"); 830 ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16); 831 m_IsReceiving = false; 832 ReceiveLength (); 833 } 834 else 835 { 836 LogPrint (eLogWarning, "NTCP2: Received AEAD verification failed "); 837 SendTerminationAndTerminate (eNTCP2DataPhaseAEADFailure); 838 } 839 } 840 } 841 ProcessNextFrame(const uint8_t * frame,size_t len)842 void NTCP2Session::ProcessNextFrame (const uint8_t * frame, size_t len) 843 { 844 size_t offset = 0; 845 while (offset < len) 846 { 847 uint8_t blk = frame[offset]; 848 offset++; 849 auto size = bufbe16toh (frame + offset); 850 offset += 2; 851 LogPrint (eLogDebug, "NTCP2: Block type ", (int)blk, " of size ", size); 852 if (size > len) 853 { 854 LogPrint (eLogError, "NTCP2: Unexpected block length ", size); 855 break; 856 } 857 switch (blk) 858 { 859 case eNTCP2BlkDateTime: 860 LogPrint (eLogDebug, "NTCP2: Datetime"); 861 break; 862 case eNTCP2BlkOptions: 863 LogPrint (eLogDebug, "NTCP2: Options"); 864 break; 865 case eNTCP2BlkRouterInfo: 866 { 867 LogPrint (eLogDebug, "NTCP2: RouterInfo flag=", (int)frame[offset]); 868 i2p::data::netdb.PostI2NPMsg (CreateI2NPMessage (eI2NPDummyMsg, frame + offset, size)); 869 break; 870 } 871 case eNTCP2BlkI2NPMessage: 872 { 873 LogPrint (eLogDebug, "NTCP2: I2NP"); 874 if (size > I2NP_MAX_MESSAGE_SIZE) 875 { 876 LogPrint (eLogError, "NTCP2: I2NP block is too long ", size); 877 break; 878 } 879 auto nextMsg = (frame[offset] == eI2NPTunnelData) ? NewI2NPTunnelMessage (true) : NewI2NPMessage (size); 880 nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header 881 if (nextMsg->len <= nextMsg->maxLen) 882 { 883 memcpy (nextMsg->GetNTCP2Header (), frame + offset, size); 884 nextMsg->FromNTCP2 (); 885 m_Handler.PutNextMessage (std::move (nextMsg)); 886 } 887 else 888 LogPrint (eLogError, "NTCP2: I2NP block is too long for I2NP message"); 889 break; 890 } 891 case eNTCP2BlkTermination: 892 if (size >= 9) 893 { 894 LogPrint (eLogDebug, "NTCP2: Rermination. reason=", (int)(frame[offset + 8])); 895 Terminate (); 896 } 897 else 898 LogPrint (eLogWarning, "NTCP2: Unexpected termination block size ", size); 899 break; 900 case eNTCP2BlkPadding: 901 LogPrint (eLogDebug, "NTCP2: Padding"); 902 break; 903 default: 904 LogPrint (eLogWarning, "NTCP2: Unknown block type ", (int)blk); 905 } 906 offset += size; 907 } 908 m_Handler.Flush (); 909 } 910 SetNextSentFrameLength(size_t frameLen,uint8_t * lengthBuf)911 void NTCP2Session::SetNextSentFrameLength (size_t frameLen, uint8_t * lengthBuf) 912 { 913 #if OPENSSL_SIPHASH 914 EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr); 915 EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8); 916 size_t l = 8; 917 EVP_DigestSignFinal (m_SendMDCtx, m_SendIV.buf, &l); 918 #else 919 i2p::crypto::Siphash<8> (m_SendIV.buf, m_SendIV.buf, 8, m_SendSipKey); 920 #endif 921 // length must be in BigEndian 922 htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key)); 923 LogPrint (eLogDebug, "NTCP2: Sent length ", frameLen); 924 } 925 SendI2NPMsgs(std::vector<std::shared_ptr<I2NPMessage>> & msgs)926 void NTCP2Session::SendI2NPMsgs (std::vector<std::shared_ptr<I2NPMessage> >& msgs) 927 { 928 if (msgs.empty () || IsTerminated ()) return; 929 930 size_t totalLen = 0; 931 std::vector<std::pair<uint8_t *, size_t> > encryptBufs; 932 std::vector<boost::asio::const_buffer> bufs; 933 std::shared_ptr<I2NPMessage> first; 934 uint8_t * macBuf = nullptr; 935 for (auto& it: msgs) 936 { 937 it->ToNTCP2 (); 938 auto buf = it->GetNTCP2Header (); 939 auto len = it->GetNTCP2Length (); 940 // block header 941 buf -= 3; 942 buf[0] = eNTCP2BlkI2NPMessage; // blk 943 htobe16buf (buf + 1, len); // size 944 len += 3; 945 totalLen += len; 946 encryptBufs.push_back ( {buf, len} ); 947 if (&it == &msgs.front ()) // first message 948 { 949 // allocate two bytes for length 950 buf -= 2; len += 2; 951 first = it; 952 } 953 if (&it == &msgs.back () && it->len + 16 < it->maxLen) // last message 954 { 955 // if it's long enough we add padding and MAC to it 956 // create padding block 957 auto paddingLen = CreatePaddingBlock (totalLen, buf + len, it->maxLen - it->len - 16); 958 if (paddingLen) 959 { 960 encryptBufs.push_back ( {buf + len, paddingLen} ); 961 len += paddingLen; 962 totalLen += paddingLen; 963 } 964 macBuf = buf + len; 965 // allocate 16 bytes for MAC 966 len += 16; 967 } 968 969 bufs.push_back (boost::asio::buffer (buf, len)); 970 } 971 972 if (!macBuf) // last block was not enough for MAC 973 { 974 // allocate send buffer 975 m_NextSendBuffer = new uint8_t[287]; // can be any size > 16, we just allocate 287 frequently 976 // create padding block 977 auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16); 978 // and padding block to encrypt and send 979 if (paddingLen) 980 encryptBufs.push_back ( {m_NextSendBuffer, paddingLen} ); 981 bufs.push_back (boost::asio::buffer (m_NextSendBuffer, paddingLen + 16)); 982 macBuf = m_NextSendBuffer + paddingLen; 983 totalLen += paddingLen; 984 } 985 uint8_t nonce[12]; 986 CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; 987 i2p::crypto::AEADChaCha20Poly1305Encrypt (encryptBufs, m_SendKey, nonce, macBuf); // encrypt buffers 988 SetNextSentFrameLength (totalLen + 16, first->GetNTCP2Header () - 5); // frame length right before first block 989 990 // send buffers 991 m_IsSending = true; 992 boost::asio::async_write (m_Socket, bufs, boost::asio::transfer_all (), 993 std::bind(&NTCP2Session::HandleI2NPMsgsSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, msgs)); 994 } 995 HandleI2NPMsgsSent(const boost::system::error_code & ecode,std::size_t bytes_transferred,std::vector<std::shared_ptr<I2NPMessage>> msgs)996 void NTCP2Session::HandleI2NPMsgsSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::vector<std::shared_ptr<I2NPMessage> > msgs) 997 { 998 HandleNextFrameSent (ecode, bytes_transferred); 999 // msgs get destroyed here 1000 } 1001 EncryptAndSendNextBuffer(size_t payloadLen)1002 void NTCP2Session::EncryptAndSendNextBuffer (size_t payloadLen) 1003 { 1004 if (IsTerminated ()) 1005 { 1006 delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; 1007 return; 1008 } 1009 // encrypt 1010 uint8_t nonce[12]; 1011 CreateNonce (m_SendSequenceNumber, nonce); m_SendSequenceNumber++; 1012 i2p::crypto::AEADChaCha20Poly1305Encrypt ({ {m_NextSendBuffer + 2, payloadLen} }, m_SendKey, nonce, m_NextSendBuffer + payloadLen + 2); 1013 SetNextSentFrameLength (payloadLen + 16, m_NextSendBuffer); 1014 // send 1015 m_IsSending = true; 1016 boost::asio::async_write (m_Socket, boost::asio::buffer (m_NextSendBuffer, payloadLen + 16 + 2), boost::asio::transfer_all (), 1017 std::bind(&NTCP2Session::HandleNextFrameSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); 1018 } 1019 HandleNextFrameSent(const boost::system::error_code & ecode,std::size_t bytes_transferred)1020 void NTCP2Session::HandleNextFrameSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) 1021 { 1022 m_IsSending = false; 1023 delete[] m_NextSendBuffer; m_NextSendBuffer = nullptr; 1024 1025 if (ecode) 1026 { 1027 if (ecode != boost::asio::error::operation_aborted) 1028 LogPrint (eLogWarning, "NTCP2: Couldn't send frame ", ecode.message ()); 1029 Terminate (); 1030 } 1031 else 1032 { 1033 m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); 1034 m_NumSentBytes += bytes_transferred; 1035 i2p::transport::transports.UpdateSentBytes (bytes_transferred); 1036 LogPrint (eLogDebug, "NTCP2: Next frame sent ", bytes_transferred); 1037 if (m_LastActivityTimestamp > m_NextRouterInfoResendTime) 1038 { 1039 m_NextRouterInfoResendTime += NTCP2_ROUTERINFO_RESEND_INTERVAL + 1040 rand ()%NTCP2_ROUTERINFO_RESEND_INTERVAL_THRESHOLD; 1041 SendRouterInfo (); 1042 } 1043 else 1044 SendQueue (); 1045 } 1046 } 1047 SendQueue()1048 void NTCP2Session::SendQueue () 1049 { 1050 if (!m_SendQueue.empty ()) 1051 { 1052 std::vector<std::shared_ptr<I2NPMessage> > msgs; 1053 size_t s = 0; 1054 while (!m_SendQueue.empty ()) 1055 { 1056 auto msg = m_SendQueue.front (); 1057 size_t len = msg->GetNTCP2Length (); 1058 if (s + len + 3 <= NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) // 3 bytes block header 1059 { 1060 msgs.push_back (msg); 1061 s += (len + 3); 1062 m_SendQueue.pop_front (); 1063 } 1064 else if (len + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) 1065 { 1066 LogPrint (eLogError, "NTCP2: I2NP message of size ", len, " can't be sent. Dropped"); 1067 m_SendQueue.pop_front (); 1068 } 1069 else 1070 break; 1071 } 1072 SendI2NPMsgs (msgs); 1073 } 1074 } 1075 CreatePaddingBlock(size_t msgLen,uint8_t * buf,size_t len)1076 size_t NTCP2Session::CreatePaddingBlock (size_t msgLen, uint8_t * buf, size_t len) 1077 { 1078 if (len < 3) return 0; 1079 len -= 3; 1080 if (msgLen < 256) msgLen = 256; // for short message padding should not be always zero 1081 size_t paddingSize = (msgLen*NTCP2_MAX_PADDING_RATIO)/100; 1082 if (msgLen + paddingSize + 3 > NTCP2_UNENCRYPTED_FRAME_MAX_SIZE) paddingSize = NTCP2_UNENCRYPTED_FRAME_MAX_SIZE - msgLen -3; 1083 if (paddingSize > len) paddingSize = len; 1084 if (paddingSize) 1085 { 1086 if (m_NextPaddingSize >= 16) 1087 { 1088 RAND_bytes ((uint8_t *)m_PaddingSizes, sizeof (m_PaddingSizes)); 1089 m_NextPaddingSize = 0; 1090 } 1091 paddingSize = m_PaddingSizes[m_NextPaddingSize++] % paddingSize; 1092 } 1093 buf[0] = eNTCP2BlkPadding; // blk 1094 htobe16buf (buf + 1, paddingSize); // size 1095 memset (buf + 3, 0, paddingSize); 1096 return paddingSize + 3; 1097 } 1098 SendRouterInfo()1099 void NTCP2Session::SendRouterInfo () 1100 { 1101 if (!IsEstablished ()) return; 1102 auto riLen = i2p::context.GetRouterInfo ().GetBufferLen (); 1103 size_t payloadLen = riLen + 4; // 3 bytes block header + 1 byte RI flag 1104 m_NextSendBuffer = new uint8_t[payloadLen + 16 + 2 + 64]; // up to 64 bytes padding 1105 m_NextSendBuffer[2] = eNTCP2BlkRouterInfo; 1106 htobe16buf (m_NextSendBuffer + 3, riLen + 1); // size 1107 m_NextSendBuffer[5] = 0; // flag 1108 memcpy (m_NextSendBuffer + 6, i2p::context.GetRouterInfo ().GetBuffer (), riLen); 1109 // padding block 1110 auto paddingSize = CreatePaddingBlock (payloadLen, m_NextSendBuffer + 2 + payloadLen, 64); 1111 payloadLen += paddingSize; 1112 // encrypt and send 1113 EncryptAndSendNextBuffer (payloadLen); 1114 } 1115 SendTermination(NTCP2TerminationReason reason)1116 void NTCP2Session::SendTermination (NTCP2TerminationReason reason) 1117 { 1118 if (!m_SendKey || 1119 #if OPENSSL_SIPHASH 1120 !m_SendMDCtx 1121 #else 1122 !m_SendSipKey 1123 #endif 1124 ) return; 1125 m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block 1126 // termination block 1127 m_NextSendBuffer[2] = eNTCP2BlkTermination; 1128 m_NextSendBuffer[3] = 0; m_NextSendBuffer[4] = 9; // 9 bytes block size 1129 htobe64buf (m_NextSendBuffer + 5, m_ReceiveSequenceNumber); 1130 m_NextSendBuffer[13] = (uint8_t)reason; 1131 // padding block 1132 auto paddingSize = CreatePaddingBlock (12, m_NextSendBuffer + 14, 19); 1133 // encrypt and send 1134 EncryptAndSendNextBuffer (paddingSize + 12); 1135 } 1136 SendTerminationAndTerminate(NTCP2TerminationReason reason)1137 void NTCP2Session::SendTerminationAndTerminate (NTCP2TerminationReason reason) 1138 { 1139 SendTermination (reason); 1140 m_Server.GetService ().post (std::bind (&NTCP2Session::Terminate, shared_from_this ())); // let termination message go 1141 } 1142 SendI2NPMessages(const std::vector<std::shared_ptr<I2NPMessage>> & msgs)1143 void NTCP2Session::SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) 1144 { 1145 m_Server.GetService ().post (std::bind (&NTCP2Session::PostI2NPMessages, shared_from_this (), msgs)); 1146 } 1147 PostI2NPMessages(std::vector<std::shared_ptr<I2NPMessage>> msgs)1148 void NTCP2Session::PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs) 1149 { 1150 if (m_IsTerminated) return; 1151 for (auto it: msgs) 1152 m_SendQueue.push_back (it); 1153 if (!m_IsSending) 1154 SendQueue (); 1155 else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE) 1156 { 1157 LogPrint (eLogWarning, "NTCP2: Outgoing messages queue size to ", 1158 GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE); 1159 Terminate (); 1160 } 1161 } 1162 SendLocalRouterInfo()1163 void NTCP2Session::SendLocalRouterInfo () 1164 { 1165 if (!IsOutgoing ()) // we send it in SessionConfirmed 1166 m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ())); 1167 } 1168 NTCP2Server()1169 NTCP2Server::NTCP2Server (): 1170 RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()), 1171 m_ProxyType(eNoProxy), m_Resolver(GetService ()) 1172 { 1173 } 1174 ~NTCP2Server()1175 NTCP2Server::~NTCP2Server () 1176 { 1177 Stop (); 1178 } 1179 Start()1180 void NTCP2Server::Start () 1181 { 1182 if (!IsRunning ()) 1183 { 1184 StartIOService (); 1185 if(UsingProxy()) 1186 { 1187 LogPrint(eLogInfo, "NTCP2: Using proxy to connect to peers"); 1188 // TODO: resolve proxy until it is resolved 1189 boost::asio::ip::tcp::resolver::query q(m_ProxyAddress, std::to_string(m_ProxyPort)); 1190 boost::system::error_code e; 1191 auto itr = m_Resolver.resolve(q, e); 1192 if(e) 1193 LogPrint(eLogError, "NTCP2: Failed to resolve proxy ", e.message()); 1194 else 1195 { 1196 m_ProxyEndpoint.reset (new boost::asio::ip::tcp::endpoint(*itr)); 1197 if (m_ProxyEndpoint) 1198 LogPrint(eLogDebug, "NTCP2: m_ProxyEndpoint ", *m_ProxyEndpoint); 1199 } 1200 } 1201 else 1202 LogPrint(eLogInfo, "NTCP2: Proxy is not used"); 1203 // start acceptors 1204 auto& addresses = context.GetRouterInfo ().GetAddresses (); 1205 for (const auto& address: addresses) 1206 { 1207 if (!address) continue; 1208 if (address->IsPublishedNTCP2 () && address->port) 1209 { 1210 if (address->IsV4()) 1211 { 1212 try 1213 { 1214 auto ep = m_Address4 ? boost::asio::ip::tcp::endpoint (m_Address4->address(), address->port): 1215 boost::asio::ip::tcp::endpoint (boost::asio::ip::tcp::v4(), address->port); 1216 m_NTCP2Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), ep)); 1217 } 1218 catch ( std::exception & ex ) 1219 { 1220 LogPrint(eLogError, "NTCP2: Failed to bind to v4 port ", address->port, ex.what()); 1221 ThrowFatal ("Unable to start IPv4 NTCP2 transport at port ", address->port, ": ", ex.what ()); 1222 continue; 1223 } 1224 1225 LogPrint (eLogInfo, "NTCP2: Start listening v4 TCP port ", address->port); 1226 auto conn = std::make_shared<NTCP2Session>(*this); 1227 m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, conn, std::placeholders::_1)); 1228 } 1229 else if (address->IsV6() && (context.SupportsV6 () || context.SupportsMesh ())) 1230 { 1231 m_NTCP2V6Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService ())); 1232 try 1233 { 1234 m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6()); 1235 m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true)); 1236 m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true)); 1237 #ifdef __linux__ 1238 if (!m_Address6 && !m_YggdrasilAddress) // only if not binded to address 1239 { 1240 // Set preference to use public IPv6 address -- tested on linux, not works on windows, and not tested on others 1241 #if (BOOST_VERSION >= 105500) 1242 typedef boost::asio::detail::socket_option::integer<BOOST_ASIO_OS_DEF(IPPROTO_IPV6), IPV6_ADDR_PREFERENCES> ipv6PreferAddr; 1243 #else 1244 typedef boost::asio::detail::socket_option::integer<IPPROTO_IPV6, IPV6_ADDR_PREFERENCES> ipv6PreferAddr; 1245 #endif 1246 m_NTCP2V6Acceptor->set_option (ipv6PreferAddr(IPV6_PREFER_SRC_PUBLIC | IPV6_PREFER_SRC_HOME | IPV6_PREFER_SRC_NONCGA)); 1247 } 1248 #endif 1249 auto ep = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v6(), address->port); 1250 if (m_Address6 && !context.SupportsMesh ()) 1251 ep = boost::asio::ip::tcp::endpoint (m_Address6->address(), address->port); 1252 else if (m_YggdrasilAddress && !context.SupportsV6 ()) 1253 ep = boost::asio::ip::tcp::endpoint (m_YggdrasilAddress->address(), address->port); 1254 m_NTCP2V6Acceptor->bind (ep); 1255 m_NTCP2V6Acceptor->listen (); 1256 1257 LogPrint (eLogInfo, "NTCP2: Start listening v6 TCP port ", address->port); 1258 auto conn = std::make_shared<NTCP2Session> (*this); 1259 m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, conn, std::placeholders::_1)); 1260 } 1261 catch ( std::exception & ex ) 1262 { 1263 LogPrint(eLogError, "NTCP2: Failed to bind to v6 port ", address->port, ": ", ex.what()); 1264 ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ()); 1265 continue; 1266 } 1267 } 1268 } 1269 } 1270 ScheduleTermination (); 1271 } 1272 } 1273 Stop()1274 void NTCP2Server::Stop () 1275 { 1276 { 1277 // we have to copy it because Terminate changes m_NTCP2Sessions 1278 auto ntcpSessions = m_NTCP2Sessions; 1279 for (auto& it: ntcpSessions) 1280 it.second->Terminate (); 1281 for (auto& it: m_PendingIncomingSessions) 1282 it->Terminate (); 1283 } 1284 m_NTCP2Sessions.clear (); 1285 1286 if (IsRunning ()) 1287 { 1288 m_TerminationTimer.cancel (); 1289 m_ProxyEndpoint = nullptr; 1290 } 1291 StopIOService (); 1292 } 1293 AddNTCP2Session(std::shared_ptr<NTCP2Session> session,bool incoming)1294 bool NTCP2Server::AddNTCP2Session (std::shared_ptr<NTCP2Session> session, bool incoming) 1295 { 1296 if (!session) return false; 1297 if (incoming) 1298 m_PendingIncomingSessions.remove (session); 1299 if (!session->GetRemoteIdentity ()) return false; 1300 auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); 1301 auto it = m_NTCP2Sessions.find (ident); 1302 if (it != m_NTCP2Sessions.end ()) 1303 { 1304 LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists"); 1305 if (incoming) 1306 // replace by new session 1307 it->second->Terminate (); 1308 else 1309 return false; 1310 } 1311 m_NTCP2Sessions.insert (std::make_pair (ident, session)); 1312 return true; 1313 } 1314 RemoveNTCP2Session(std::shared_ptr<NTCP2Session> session)1315 void NTCP2Server::RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session) 1316 { 1317 if (session && session->GetRemoteIdentity ()) 1318 m_NTCP2Sessions.erase (session->GetRemoteIdentity ()->GetIdentHash ()); 1319 } 1320 FindNTCP2Session(const i2p::data::IdentHash & ident)1321 std::shared_ptr<NTCP2Session> NTCP2Server::FindNTCP2Session (const i2p::data::IdentHash& ident) 1322 { 1323 auto it = m_NTCP2Sessions.find (ident); 1324 if (it != m_NTCP2Sessions.end ()) 1325 return it->second; 1326 return nullptr; 1327 } 1328 Connect(std::shared_ptr<NTCP2Session> conn)1329 void NTCP2Server::Connect(std::shared_ptr<NTCP2Session> conn) 1330 { 1331 if (!conn || conn->GetRemoteEndpoint ().address ().is_unspecified ()) 1332 { 1333 LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); 1334 return; 1335 } 1336 LogPrint (eLogDebug, "NTCP2: Connecting to ", conn->GetRemoteEndpoint ()); 1337 GetService ().post([this, conn]() 1338 { 1339 if (this->AddNTCP2Session (conn)) 1340 { 1341 auto timer = std::make_shared<boost::asio::deadline_timer>(GetService ()); 1342 auto timeout = NTCP2_CONNECT_TIMEOUT * 5; 1343 conn->SetTerminationTimeout(timeout * 2); 1344 timer->expires_from_now (boost::posix_time::seconds(timeout)); 1345 timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) 1346 { 1347 if (ecode != boost::asio::error::operation_aborted) 1348 { 1349 LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); 1350 conn->Terminate (); 1351 } 1352 }); 1353 // bind to local address 1354 std::shared_ptr<boost::asio::ip::tcp::endpoint> localAddress; 1355 if (conn->GetRemoteEndpoint ().address ().is_v6 ()) 1356 { 1357 if (i2p::util::net::IsYggdrasilAddress (conn->GetRemoteEndpoint ().address ())) 1358 localAddress = m_YggdrasilAddress; 1359 else 1360 localAddress = m_Address6; 1361 conn->GetSocket ().open (boost::asio::ip::tcp::v6 ()); 1362 } 1363 else 1364 { 1365 localAddress = m_Address4; 1366 conn->GetSocket ().open (boost::asio::ip::tcp::v4 ()); 1367 } 1368 if (localAddress) 1369 { 1370 boost::system::error_code ec; 1371 conn->GetSocket ().bind (*localAddress, ec); 1372 if (ec) 1373 LogPrint (eLogError, "NTCP2: Can't bind to ", localAddress->address ().to_string (), ": ", ec.message ()); 1374 } 1375 conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer)); 1376 } 1377 else 1378 conn->Terminate (); 1379 }); 1380 } 1381 HandleConnect(const boost::system::error_code & ecode,std::shared_ptr<NTCP2Session> conn,std::shared_ptr<boost::asio::deadline_timer> timer)1382 void NTCP2Server::HandleConnect (const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer) 1383 { 1384 timer->cancel (); 1385 if (ecode) 1386 { 1387 LogPrint (eLogInfo, "NTCP2: Connect error ", ecode.message ()); 1388 conn->Terminate (); 1389 } 1390 else 1391 { 1392 LogPrint (eLogDebug, "NTCP2: Connected to ", conn->GetRemoteEndpoint ()); 1393 conn->ClientLogin (); 1394 } 1395 } 1396 HandleAccept(std::shared_ptr<NTCP2Session> conn,const boost::system::error_code & error)1397 void NTCP2Server::HandleAccept (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error) 1398 { 1399 if (!error) 1400 { 1401 boost::system::error_code ec; 1402 auto ep = conn->GetSocket ().remote_endpoint(ec); 1403 if (!ec) 1404 { 1405 LogPrint (eLogDebug, "NTCP2: Connected from ", ep); 1406 if (conn) 1407 { 1408 conn->SetRemoteEndpoint (ep); 1409 conn->ServerLogin (); 1410 m_PendingIncomingSessions.push_back (conn); 1411 conn = nullptr; 1412 } 1413 } 1414 else 1415 LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); 1416 } 1417 else 1418 LogPrint (eLogError, "NTCP2: Accept error ", error.message ()); 1419 1420 if (error != boost::asio::error::operation_aborted) 1421 { 1422 if (!conn) // connection is used, create new one 1423 conn = std::make_shared<NTCP2Session> (*this); 1424 else // reuse failed 1425 conn->Close (); 1426 m_NTCP2Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAccept, this, 1427 conn, std::placeholders::_1)); 1428 } 1429 } 1430 HandleAcceptV6(std::shared_ptr<NTCP2Session> conn,const boost::system::error_code & error)1431 void NTCP2Server::HandleAcceptV6 (std::shared_ptr<NTCP2Session> conn, const boost::system::error_code& error) 1432 { 1433 if (!error) 1434 { 1435 boost::system::error_code ec; 1436 auto ep = conn->GetSocket ().remote_endpoint(ec); 1437 if (!ec) 1438 { 1439 LogPrint (eLogDebug, "NTCP2: Connected from ", ep); 1440 if (conn) 1441 { 1442 conn->SetRemoteEndpoint (ep); 1443 conn->ServerLogin (); 1444 m_PendingIncomingSessions.push_back (conn); 1445 } 1446 } 1447 else 1448 LogPrint (eLogError, "NTCP2: Connected from error ", ec.message ()); 1449 } 1450 1451 if (error != boost::asio::error::operation_aborted) 1452 { 1453 conn = std::make_shared<NTCP2Session> (*this); 1454 m_NTCP2V6Acceptor->async_accept(conn->GetSocket (), std::bind (&NTCP2Server::HandleAcceptV6, this, 1455 conn, std::placeholders::_1)); 1456 } 1457 } 1458 ScheduleTermination()1459 void NTCP2Server::ScheduleTermination () 1460 { 1461 m_TerminationTimer.expires_from_now (boost::posix_time::seconds(NTCP2_TERMINATION_CHECK_TIMEOUT)); 1462 m_TerminationTimer.async_wait (std::bind (&NTCP2Server::HandleTerminationTimer, 1463 this, std::placeholders::_1)); 1464 } 1465 HandleTerminationTimer(const boost::system::error_code & ecode)1466 void NTCP2Server::HandleTerminationTimer (const boost::system::error_code& ecode) 1467 { 1468 if (ecode != boost::asio::error::operation_aborted) 1469 { 1470 auto ts = i2p::util::GetSecondsSinceEpoch (); 1471 // established 1472 for (auto& it: m_NTCP2Sessions) 1473 if (it.second->IsTerminationTimeoutExpired (ts)) 1474 { 1475 auto session = it.second; 1476 LogPrint (eLogDebug, "NTCP2: No activity for ", session->GetTerminationTimeout (), " seconds"); 1477 session->TerminateByTimeout (); // it doesn't change m_NTCP2Session right a way 1478 } 1479 else 1480 it.second->DeleteNextReceiveBuffer (ts); 1481 // pending 1482 for (auto it = m_PendingIncomingSessions.begin (); it != m_PendingIncomingSessions.end ();) 1483 { 1484 if ((*it)->IsEstablished () || (*it)->IsTerminationTimeoutExpired (ts)) 1485 { 1486 (*it)->Terminate (); 1487 it = m_PendingIncomingSessions.erase (it); // established of expired 1488 } 1489 else if ((*it)->IsTerminated ()) 1490 it = m_PendingIncomingSessions.erase (it); // already terminated 1491 else 1492 it++; 1493 } 1494 1495 ScheduleTermination (); 1496 } 1497 } 1498 ConnectWithProxy(std::shared_ptr<NTCP2Session> conn)1499 void NTCP2Server::ConnectWithProxy (std::shared_ptr<NTCP2Session> conn) 1500 { 1501 if(!m_ProxyEndpoint) return; 1502 if (!conn || conn->GetRemoteEndpoint ().address ().is_unspecified ()) 1503 { 1504 LogPrint (eLogError, "NTCP2: Can't connect to unspecified address"); 1505 return; 1506 } 1507 GetService().post([this, conn]() 1508 { 1509 if (this->AddNTCP2Session (conn)) 1510 { 1511 auto timer = std::make_shared<boost::asio::deadline_timer>(GetService()); 1512 auto timeout = NTCP2_CONNECT_TIMEOUT * 5; 1513 conn->SetTerminationTimeout(timeout * 2); 1514 timer->expires_from_now (boost::posix_time::seconds(timeout)); 1515 timer->async_wait ([conn, timeout](const boost::system::error_code& ecode) 1516 { 1517 if (ecode != boost::asio::error::operation_aborted) 1518 { 1519 LogPrint (eLogInfo, "NTCP2: Not connected in ", timeout, " seconds"); 1520 conn->Terminate (); 1521 } 1522 }); 1523 conn->GetSocket ().async_connect (*m_ProxyEndpoint, std::bind (&NTCP2Server::HandleProxyConnect, this, std::placeholders::_1, conn, timer)); 1524 } 1525 }); 1526 } 1527 UseProxy(ProxyType proxytype,const std::string & addr,uint16_t port,const std::string & user,const std::string & pass)1528 void NTCP2Server::UseProxy(ProxyType proxytype, const std::string& addr, uint16_t port, 1529 const std::string& user, const std::string& pass) 1530 { 1531 m_ProxyType = proxytype; 1532 m_ProxyAddress = addr; 1533 m_ProxyPort = port; 1534 if (m_ProxyType == eHTTPProxy ) 1535 m_ProxyAuthorization = i2p::http::CreateBasicAuthorizationString (user, pass); 1536 } 1537 HandleProxyConnect(const boost::system::error_code & ecode,std::shared_ptr<NTCP2Session> conn,std::shared_ptr<boost::asio::deadline_timer> timer)1538 void NTCP2Server::HandleProxyConnect(const boost::system::error_code& ecode, std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer) 1539 { 1540 if (ecode) 1541 { 1542 LogPrint(eLogWarning, "NTCP2: Failed to connect to proxy ", ecode.message()); 1543 timer->cancel(); 1544 conn->Terminate(); 1545 return; 1546 } 1547 switch (m_ProxyType) 1548 { 1549 case eSocksProxy: 1550 { 1551 // TODO: support username/password auth etc 1552 static const uint8_t buff[3] = {0x05, 0x01, 0x00}; 1553 boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(), 1554 [] (const boost::system::error_code & ec, std::size_t transferred) 1555 { 1556 (void) transferred; 1557 if(ec) 1558 { 1559 LogPrint(eLogWarning, "NTCP2: SOCKS5 write error ", ec.message()); 1560 } 1561 }); 1562 auto readbuff = std::make_shared<std::vector<uint8_t> >(2); 1563 boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 2), 1564 [this, readbuff, timer, conn](const boost::system::error_code & ec, std::size_t transferred) 1565 { 1566 if(ec) 1567 { 1568 LogPrint(eLogError, "NTCP2: SOCKS5 read error ", ec.message()); 1569 timer->cancel(); 1570 conn->Terminate(); 1571 return; 1572 } 1573 else if(transferred == 2) 1574 { 1575 if((*readbuff)[1] == 0x00) 1576 { 1577 AfterSocksHandshake(conn, timer); 1578 return; 1579 } 1580 else if ((*readbuff)[1] == 0xff) 1581 { 1582 LogPrint(eLogError, "NTCP2: SOCKS5 proxy rejected authentication"); 1583 timer->cancel(); 1584 conn->Terminate(); 1585 return; 1586 } 1587 LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]); 1588 } 1589 LogPrint(eLogError, "NTCP2: SOCKS5 server gave invalid response"); 1590 timer->cancel(); 1591 conn->Terminate(); 1592 }); 1593 break; 1594 } 1595 case eHTTPProxy: 1596 { 1597 auto& ep = conn->GetRemoteEndpoint (); 1598 i2p::http::HTTPReq req; 1599 req.method = "CONNECT"; 1600 req.version ="HTTP/1.1"; 1601 if(ep.address ().is_v6 ()) 1602 req.uri = "[" + ep.address ().to_string() + "]:" + std::to_string(ep.port ()); 1603 else 1604 req.uri = ep.address ().to_string() + ":" + std::to_string(ep.port ()); 1605 if (!m_ProxyAuthorization.empty ()) 1606 req.AddHeader("Proxy-Authorization", m_ProxyAuthorization); 1607 1608 boost::asio::streambuf writebuff; 1609 std::ostream out(&writebuff); 1610 out << req.to_string(); 1611 1612 boost::asio::async_write(conn->GetSocket(), writebuff.data(), boost::asio::transfer_all(), 1613 [](const boost::system::error_code & ec, std::size_t transferred) 1614 { 1615 (void) transferred; 1616 if(ec) 1617 LogPrint(eLogError, "NTCP2: HTTP proxy write error ", ec.message()); 1618 }); 1619 1620 boost::asio::streambuf * readbuff = new boost::asio::streambuf; 1621 boost::asio::async_read_until(conn->GetSocket(), *readbuff, "\r\n\r\n", 1622 [readbuff, timer, conn] (const boost::system::error_code & ec, std::size_t transferred) 1623 { 1624 if(ec) 1625 { 1626 LogPrint(eLogError, "NTCP2: HTTP proxy read error ", ec.message()); 1627 timer->cancel(); 1628 conn->Terminate(); 1629 } 1630 else 1631 { 1632 readbuff->commit(transferred); 1633 i2p::http::HTTPRes res; 1634 if(res.parse(boost::asio::buffer_cast<const char*>(readbuff->data()), readbuff->size()) > 0) 1635 { 1636 if(res.code == 200) 1637 { 1638 timer->cancel(); 1639 conn->ClientLogin(); 1640 delete readbuff; 1641 return; 1642 } 1643 else 1644 LogPrint(eLogError, "NTCP2: HTTP proxy rejected request ", res.code); 1645 } 1646 else 1647 LogPrint(eLogError, "NTCP2: HTTP proxy gave malformed response"); 1648 timer->cancel(); 1649 conn->Terminate(); 1650 delete readbuff; 1651 } 1652 }); 1653 break; 1654 } 1655 default: 1656 LogPrint(eLogError, "NTCP2: Unknown proxy type, invalid state"); 1657 } 1658 } 1659 AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn,std::shared_ptr<boost::asio::deadline_timer> timer)1660 void NTCP2Server::AfterSocksHandshake(std::shared_ptr<NTCP2Session> conn, std::shared_ptr<boost::asio::deadline_timer> timer) 1661 { 1662 // build request 1663 size_t sz = 6; // header + port 1664 auto buff = std::make_shared<std::vector<int8_t> >(256); 1665 auto readbuff = std::make_shared<std::vector<int8_t> >(256); 1666 (*buff)[0] = 0x05; 1667 (*buff)[1] = 0x01; 1668 (*buff)[2] = 0x00; 1669 1670 auto& ep = conn->GetRemoteEndpoint (); 1671 if(ep.address ().is_v4 ()) 1672 { 1673 (*buff)[3] = 0x01; 1674 auto addrbytes = ep.address ().to_v4().to_bytes(); 1675 sz += 4; 1676 memcpy(buff->data () + 4, addrbytes.data(), 4); 1677 } 1678 else if (ep.address ().is_v6 ()) 1679 { 1680 (*buff)[3] = 0x04; 1681 auto addrbytes = ep.address ().to_v6().to_bytes(); 1682 sz += 16; 1683 memcpy(buff->data () + 4, addrbytes.data(), 16); 1684 } 1685 else 1686 { 1687 // We mustn't really fall here because all connections are made to IP addresses 1688 LogPrint(eLogError, "NTCP2: Tried to connect to unexpected address via proxy"); 1689 return; 1690 } 1691 htobe16buf(buff->data () + sz - 2, ep.port ()); 1692 boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff->data (), sz), boost::asio::transfer_all(), 1693 [buff](const boost::system::error_code & ec, std::size_t written) 1694 { 1695 if(ec) 1696 { 1697 LogPrint(eLogError, "NTCP2: Failed to write handshake to socks proxy ", ec.message()); 1698 return; 1699 } 1700 }); 1701 1702 boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 10), 1703 [timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred) 1704 { 1705 if(e) 1706 { 1707 LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message()); 1708 } 1709 else if(transferred == sz) 1710 { 1711 if((*readbuff)[1] == 0x00) 1712 { 1713 timer->cancel(); 1714 conn->ClientLogin(); 1715 return; 1716 } 1717 } 1718 timer->cancel(); 1719 conn->Terminate(); 1720 }); 1721 } 1722 SetLocalAddress(const boost::asio::ip::address & localAddress)1723 void NTCP2Server::SetLocalAddress (const boost::asio::ip::address& localAddress) 1724 { 1725 auto addr = std::make_shared<boost::asio::ip::tcp::endpoint>(boost::asio::ip::tcp::endpoint(localAddress, 0)); 1726 if (localAddress.is_v6 ()) 1727 { 1728 if (i2p::util::net::IsYggdrasilAddress (localAddress)) 1729 m_YggdrasilAddress = addr; 1730 else 1731 m_Address6 = addr; 1732 } 1733 else 1734 m_Address4 = addr; 1735 } 1736 } 1737 } 1738