diff --git a/tests/test_networkengine.cpp b/tests/test_networkengine.cpp index 3df9c462..ef53b1be 100644 --- a/tests/test_networkengine.cpp +++ b/tests/test_networkengine.cpp @@ -1854,6 +1854,31 @@ establishSession(TransportTestNode& a, TransportTestNode& b) CPPUNIT_ASSERT(done); } +void +NetworkEngineTester::testTransportPrivateClientKeepsAuthorization() +{ + auto authority = transport::Authority::generate(); + TransportTestNode client("127.0.0.2", privateTransport(authority), 1, 0, [](net::NetworkConfig& config) { + config.is_client = true; + }); + TransportTestNode server("127.0.0.3", privateTransport(authority), 2); + establishSession(client, server); + CPPUNIT_ASSERT(server.known.empty()); + CPPUNIT_ASSERT(not server.engine->cache.getNode(client.id, AF_INET)); + + advanceTime(server, std::chrono::minutes(30)); + for (int attempt = 0; attempt < 3; ++attempt) { + bool done = false; + client.ping(client.node(server), done); + CPPUNIT_ASSERT(isEnvelope(client.socket->sends.at(0), transport::EnvelopeType::Data)); + client.deliverTo(server); + server.deliverTo(client); + CPPUNIT_ASSERT(done); + CPPUNIT_ASSERT(server.known.empty()); + CPPUNIT_ASSERT(not server.engine->cache.getNode(client.id, AF_INET)); + } +} + /* Initial envelope from a fresh identity, as anyone can send from any address */ static Blob makeInitialPing(const transport::KeyPair& receiver, Tid tid) @@ -3019,6 +3044,52 @@ NetworkEngineTester::testRateLimitCryptoAdmission() CPPUNIT_ASSERT(done); } +void +NetworkEngineTester::testRateLimitCachedSessionCredentials() +{ + auto authority = transport::Authority::generate(); + for (bool cached : {false, true}) { + auto sender = privateTransport(authority); + auto ephemeral = transport::KeyPair::generate(); + auto from = makeIPv4("127.0.0.2", 4222); + TransportTestNode receiver("127.0.0.3", privateTransport(authority), 2, 0, rateLimits(-1, -1, 1)); + auto local = receiver.engine->epoch_.ephemeral(from); + auto keys = *transport::sessionKeys(receiver.key, local, sender.key.pub, ephemeral.pub, 0); + if (cached) + receiver.engine->epoch_.store(from, {local.pub, sender.key.pub, ephemeral.pub, keys}); + auto ping = makePingPacketBlob(transport::nodeId(sender.key.pub), 200); + auto send = [&](const Blob& credential) { + auto packet = transport::seal(keys.rx, + transport::EnvelopeType::Session, + sender.key.pub, + ephemeral.pub, + ping.data(), + ping.size(), + credential); + receiver.engine->processMessage(packet.data(), packet.size(), from); + }; + auto data = transport::sealData(keys.rx, ping.data(), ping.size()); + receiver.engine->processMessage(data.data(), data.size(), from); + CPPUNIT_ASSERT(receiver.takeSent().empty()); + + auto invalid = sender.credential; + invalid.signature[0] ^= 1; + for (int attempt = 0; attempt < 3; ++attempt) + send(invalid.pack()); + CPPUNIT_ASSERT(receiver.takeSent().empty()); + send(sender.credential.pack()); + CPPUNIT_ASSERT(receiver.takeSent().empty()); + + advanceTime(receiver, std::chrono::seconds(2)); + send(sender.credential.pack()); + CPPUNIT_ASSERT_EQUAL(size_t {1}, receiver.takeSent().size()); + CPPUNIT_ASSERT(not receiver.engine->cryptoLimiter_.limit(from, receiver.scheduler.time())); + + send(sender.credential.pack()); + CPPUNIT_ASSERT_EQUAL(size_t {1}, receiver.takeSent().size()); + } +} + void NetworkEngineTester::testRateLimitCryptoPerPrefix() { diff --git a/tests/test_networkengine.h b/tests/test_networkengine.h index 6a029c76..993c35ad 100644 --- a/tests/test_networkengine.h +++ b/tests/test_networkengine.h @@ -35,6 +35,7 @@ class NetworkEngineTester : public CppUnit::TestFixture CPPUNIT_TEST(testTransportIgnoresForgedNodeListKey); CPPUNIT_TEST(testTransportPlaintextDoesNotMoveKeyedNode); CPPUNIT_TEST(testTransportPrivateNetwork); + CPPUNIT_TEST(testTransportPrivateClientKeepsAuthorization); CPPUNIT_TEST(testTransportPrivateNetworkRejectsOutsiders); CPPUNIT_TEST(testTransportEpochRotation); CPPUNIT_TEST(testTransportPeerRestart); @@ -76,6 +77,7 @@ class NetworkEngineTester : public CppUnit::TestFixture CPPUNIT_TEST(testTransportEncryptionFailureDoesNotSendPlaintext); CPPUNIT_TEST(testRateLimitSeparatesSessionRequests); CPPUNIT_TEST(testRateLimitCryptoAdmission); + CPPUNIT_TEST(testRateLimitCachedSessionCredentials); CPPUNIT_TEST(testRateLimitCryptoPerPrefix); CPPUNIT_TEST(testRateLimitReservesExpectedReplies); #endif @@ -110,6 +112,7 @@ public: void testTransportIgnoresForgedNodeListKey(); void testTransportPlaintextDoesNotMoveKeyedNode(); void testTransportPrivateNetwork(); + void testTransportPrivateClientKeepsAuthorization(); void testTransportPrivateNetworkRejectsOutsiders(); void testTransportEpochRotation(); void testTransportPeerRestart(); @@ -151,6 +154,7 @@ public: void testTransportEncryptionFailureDoesNotSendPlaintext(); void testRateLimitSeparatesSessionRequests(); void testRateLimitCryptoAdmission(); + void testRateLimitCachedSessionCredentials(); void testRateLimitCryptoPerPrefix(); void testRateLimitReservesExpectedReplies(); #endif