summaryrefslogtreecommitdiffstats
path: root/net/quic
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-13 03:23:57 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-13 03:23:57 +0000
commit72818ea6b7334c2a4b94aa78c4907c01e9720c1c (patch)
tree43520232e1d1a3a2d834d102af8984a67ecd61ce /net/quic
parent1ba66adaad90e014692e02290cdb83c7b038a286 (diff)
downloadchromium_src-72818ea6b7334c2a4b94aa78c4907c01e9720c1c.zip
chromium_src-72818ea6b7334c2a4b94aa78c4907c01e9720c1c.tar.gz
chromium_src-72818ea6b7334c2a4b94aa78c4907c01e9720c1c.tar.bz2
Add QuicCryptoServerStream (and test) and get CryptoUtils working.
Review URL: https://chromiumcodereview.appspot.com/12452007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187757 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic')
-rw-r--r--net/quic/quic_crypto_client_stream_test.cc155
-rw-r--r--net/quic/quic_crypto_server_stream.cc73
-rw-r--r--net/quic/quic_crypto_server_stream.h41
-rw-r--r--net/quic/quic_crypto_server_stream_test.cc122
-rw-r--r--net/quic/test_tools/crypto_test_utils.cc12
5 files changed, 309 insertions, 94 deletions
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index ed59716..29ae7cb 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -4,12 +4,14 @@
#include "net/quic/quic_crypto_client_stream.h"
+#include "base/memory/scoped_ptr.h"
#include "net/quic/crypto/quic_decrypter.h"
#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
#include "net/quic/test_tools/quic_test_utils.h"
-
-using base::StringPiece;
-using std::vector;
+#include "net/quic/test_tools/simple_quic_framer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace net {
namespace test {
@@ -19,61 +21,85 @@ const char kServerHostname[] = "localhost";
class TestQuicVisitor : public NoOpFramerVisitor {
public:
- TestQuicVisitor() {}
+ TestQuicVisitor()
+ : frame_valid_(false) {
+ }
// NoOpFramerVisitor
- virtual void OnStreamFrame(const QuicStreamFrame& frame) OVERRIDE {
+ virtual void OnStreamFrame(const QuicStreamFrame& frame) {
frame_ = frame;
+ frame_valid_ = true;
}
+ bool frame_valid() const {
+ return frame_valid_;
+ }
QuicStreamFrame* frame() { return &frame_; }
private:
QuicStreamFrame frame_;
+ bool frame_valid_;
DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor);
};
-// The same as MockHelper, except that WritePacketToWire() checks whether
-// the packet has the expected contents.
-class TestMockHelper : public MockHelper {
+// The same as MockSession, except that WriteData() is not mocked.
+class TestMockSession : public MockSession {
public:
- TestMockHelper() : packet_count_(0) {}
- virtual ~TestMockHelper() {}
+ TestMockSession(QuicConnection* connection, bool is_server)
+ : MockSession(connection, is_server) {
+ }
+ virtual ~TestMockSession() {}
- virtual int WritePacketToWire(const QuicEncryptedPacket& packet,
- int* error) OVERRIDE {
- packet_count_++;
+ virtual QuicConsumedData WriteData(QuicStreamId id, base::StringPiece data,
+ QuicStreamOffset offset, bool fin) {
+ return QuicSession::WriteData(id, data, offset, fin);
+ }
+};
- // The first packet should be ClientHello.
- if (packet_count_ == 1) {
- CheckClientHelloPacket(packet);
- }
+class QuicCryptoClientStreamTest : public ::testing::Test {
+ public:
+ QuicCryptoClientStreamTest()
+ : addr_(),
+ connection_(new PacketSavingConnection(1, addr_)),
+ session_(connection_, true),
+ stream_(&session_, kServerHostname) {
+ }
- return MockHelper::WritePacketToWire(packet, error);
+ void CompleteCryptoHandshake() {
+ EXPECT_TRUE(stream_.CryptoConnect());
+ CryptoTestUtils::HandshakeWithFakeServer(connection_, &stream_);
}
- private:
- void CheckClientHelloPacket(const QuicEncryptedPacket& packet);
+ void ConstructHandshakeMessage() {
+ CryptoFramer framer;
+ message_data_.reset(framer.ConstructHandshakeMessage(message_));
+ }
- int packet_count_;
+ IPEndPoint addr_;
+ PacketSavingConnection* connection_;
+ TestMockSession session_;
+ QuicCryptoClientStream stream_;
+ CryptoHandshakeMessage message_;
+ scoped_ptr<QuicData> message_data_;
};
-void TestMockHelper::CheckClientHelloPacket(
- const QuicEncryptedPacket& packet) {
- QuicFramer quic_framer(kQuicVersion1,
- QuicDecrypter::Create(kNULL),
- QuicEncrypter::Create(kNULL));
- TestQuicVisitor quic_visitor;
- quic_framer.set_visitor(&quic_visitor);
- ASSERT_TRUE(quic_framer.ProcessPacket(packet));
- EXPECT_EQ(kCryptoStreamId, quic_visitor.frame()->stream_id);
- EXPECT_FALSE(quic_visitor.frame()->fin);
- EXPECT_EQ(0u, quic_visitor.frame()->offset);
-
- // Check quic_visitor.frame()->data.
- scoped_ptr<CryptoHandshakeMessage> chlo(
- CryptoFramer::ParseMessage(quic_visitor.frame()->data));
+TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
+ EXPECT_FALSE(stream_.handshake_complete());
+}
+
+TEST_F(QuicCryptoClientStreamTest, ClientHelloContents) {
+ EXPECT_TRUE(stream_.CryptoConnect());
+
+ SimpleQuicFramer framer;
+ ASSERT_TRUE(framer.ProcessPacket(*connection_->packets_[0]));
+ ASSERT_EQ(1u, framer.stream_frames().size());
+ const QuicStreamFrame& frame(framer.stream_frames()[0]);
+ EXPECT_EQ(kCryptoStreamId, frame.stream_id);
+ EXPECT_FALSE(frame.fin);
+ EXPECT_EQ(0u, frame.offset);
+
+ scoped_ptr<CryptoHandshakeMessage> chlo(framer.HandshakeMessage(0));
EXPECT_EQ(kCHLO, chlo->tag);
CryptoTagValueMap& tag_value_map = chlo->tag_value_map;
@@ -103,9 +129,6 @@ void TestMockHelper::CheckClientHelloPacket(
memcpy(&cipher[0], &tag_value_map[kAEAD][0], 4);
EXPECT_EQ(kAESG, cipher[0]);
- // TODO(agl): reenable these once the non-crypto parts of the handshake have
- // been split from crypto/
-#if 0
// kICSL
ASSERT_EQ(4u, tag_value_map[kICSL].size());
uint32 idle_lifetime;
@@ -123,66 +146,20 @@ void TestMockHelper::CheckClientHelloPacket(
CryptoTag congestion[1];
memcpy(&congestion[0], &tag_value_map[kCGST][0], 4);
EXPECT_EQ(kQBIC, congestion[0]);
-#endif
-}
-
-// The same as MockSession, except that WriteData() is not mocked.
-class TestMockSession : public MockSession {
- public:
- TestMockSession(QuicConnection* connection, bool is_server)
- : MockSession(connection, is_server) {
- }
- virtual ~TestMockSession() {}
-
- virtual QuicConsumedData WriteData(QuicStreamId id,
- StringPiece data,
- QuicStreamOffset offset,
- bool fin) OVERRIDE {
- return QuicSession::WriteData(id, data, offset, fin);
- }
-};
-
-class QuicCryptoClientStreamTest : public ::testing::Test {
- public:
- QuicCryptoClientStreamTest()
- : connection_(new MockConnection(1, addr_, new TestMockHelper())),
- session_(connection_, true),
- stream_(&session_, kServerHostname) {
- message_ = CreateShloMessage(&clock_, &random_, "www.google.com");
- ConstructHandshakeMessage();
- }
-
- void ConstructHandshakeMessage() {
- CryptoFramer framer;
- message_data_.reset(framer.ConstructHandshakeMessage(message_));
- }
-
- IPEndPoint addr_;
- MockConnection* connection_;
- TestMockSession session_;
- MockClock clock_;
- MockRandom random_;
- QuicCryptoClientStream stream_;
- CryptoHandshakeMessage message_;
- scoped_ptr<QuicData> message_data_;
-};
-
-TEST_F(QuicCryptoClientStreamTest, NotInitiallyConected) {
- EXPECT_FALSE(stream_.handshake_complete());
}
TEST_F(QuicCryptoClientStreamTest, ConnectedAfterSHLO) {
- stream_.CryptoConnect();
- stream_.ProcessData(message_data_->data(), message_data_->length());
+ CompleteCryptoHandshake();
EXPECT_TRUE(stream_.handshake_complete());
}
TEST_F(QuicCryptoClientStreamTest, MessageAfterHandshake) {
- stream_.CryptoConnect();
- stream_.ProcessData(message_data_->data(), message_data_->length());
+ CompleteCryptoHandshake();
EXPECT_CALL(*connection_, SendConnectionClose(
QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
+ message_.tag = kCHLO;
+ ConstructHandshakeMessage();
stream_.ProcessData(message_data_->data(), message_data_->length());
}
diff --git a/net/quic/quic_crypto_server_stream.cc b/net/quic/quic_crypto_server_stream.cc
new file mode 100644
index 0000000..0f4d4f4
--- /dev/null
+++ b/net/quic/quic_crypto_server_stream.cc
@@ -0,0 +1,73 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_crypto_server_stream.h"
+
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_session.h"
+
+namespace net {
+
+QuicCryptoServerStream::QuicCryptoServerStream(QuicSession* session)
+ : QuicCryptoStream(session) {
+ config_.SetDefaults();
+ // Use hardcoded crypto parameters for now.
+ CryptoHandshakeMessage extra_tags;
+ config_.ToHandshakeMessage(&extra_tags);
+ // TODO(agl): AddTestingConfig generates a new, random config. In the future
+ // this will be replaced with a real source of configs.
+ scoped_ptr<CryptoTagValueMap> config_tags(
+ crypto_config_.AddTestingConfig(session->connection()->random_generator(),
+ session->connection()->clock(),
+ extra_tags));
+ // If we were using the same config in many servers then we would have to
+ // parse a QuicConfig from config_tags here.
+}
+
+QuicCryptoServerStream::~QuicCryptoServerStream() {
+}
+
+void QuicCryptoServerStream::OnHandshakeMessage(
+ const CryptoHandshakeMessage& message) {
+ // Do not process handshake messages after the handshake is complete.
+ if (handshake_complete()) {
+ CloseConnection(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
+ return;
+ }
+
+ if (message.tag != kCHLO) {
+ CloseConnection(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
+ return;
+ }
+
+ string error_details;
+ QuicErrorCode error = config_.ProcessPeerHandshake(
+ message, CryptoUtils::LOCAL_PRIORITY, &negotiated_params_,
+ &error_details);
+ if (error != QUIC_NO_ERROR) {
+ CloseConnectionWithDetails(error, "negotiated params");
+ return;
+ }
+
+ CryptoHandshakeMessage shlo;
+ CryptoUtils::GenerateNonce(session()->connection()->clock(),
+ session()->connection()->random_generator(),
+ &server_nonce_);
+ QuicCryptoNegotiatedParams params;
+ crypto_config_.ProcessClientHello(message, server_nonce_, &shlo, &params,
+ &error_details);
+ if (!error_details.empty()) {
+ DLOG(INFO) << "Rejecting CHLO: " << error_details;
+ }
+ config_.ToHandshakeMessage(&shlo);
+ SendHandshakeMessage(shlo);
+
+ // TODO(rch): correctly validate the message
+ SetHandshakeComplete(QUIC_NO_ERROR);
+ return;
+}
+
+} // namespace net
diff --git a/net/quic/quic_crypto_server_stream.h b/net/quic/quic_crypto_server_stream.h
new file mode 100644
index 0000000..5f9ddd1
--- /dev/null
+++ b/net/quic/quic_crypto_server_stream.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
+#define NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
+
+#include <string>
+
+#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/quic_crypto_stream.h"
+
+namespace net {
+
+class QuicSession;
+struct CryptoHandshakeMessage;
+
+class NET_EXPORT_PRIVATE QuicCryptoServerStream : public QuicCryptoStream {
+ public:
+ explicit QuicCryptoServerStream(QuicSession* session);
+ virtual ~QuicCryptoServerStream();
+
+ // CryptoFramerVisitorInterface implementation
+ virtual void OnHandshakeMessage(
+ const CryptoHandshakeMessage& message) OVERRIDE;
+
+ private:
+ // config_ contains non-crypto parameters that are negotiated in the crypto
+ // handshake.
+ QuicConfig config_;
+ // crypto_config_ contains crypto parameters for the handshake.
+ QuicCryptoServerConfig crypto_config_;
+ std::string server_nonce_;
+
+ QuicNegotiatedParameters negotiated_params_;
+ QuicCryptoNegotiatedParams crypto_negotiated_params_;
+};
+
+} // namespace net
+
+#endif // NET_QUIC_QUIC_CRYPTO_SERVER_STREAM_H_
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
new file mode 100644
index 0000000..995cb6b
--- /dev/null
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -0,0 +1,122 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_crypto_server_stream.h"
+
+#include <map>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "net/quic/crypto/crypto_framer.h"
+#include "net/quic/crypto/crypto_handshake.h"
+#include "net/quic/crypto/crypto_protocol.h"
+#include "net/quic/crypto/crypto_utils.h"
+#include "net/quic/crypto/quic_decrypter.h"
+#include "net/quic/crypto/quic_encrypter.h"
+#include "net/quic/quic_protocol.h"
+#include "net/quic/quic_session.h"
+#include "net/quic/test_tools/crypto_test_utils.h"
+#include "net/quic/test_tools/quic_test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+class QuicConnection;
+class ReliableQuicStream;
+} // namespace net
+
+using testing::_;
+
+namespace net {
+namespace test {
+namespace {
+
+// TODO(agl): Use rch's utility class for parsing a message when committed.
+class TestQuicVisitor : public NoOpFramerVisitor {
+ public:
+ TestQuicVisitor() {}
+
+ // NoOpFramerVisitor
+ virtual void OnStreamFrame(const QuicStreamFrame& frame) {
+ frame_ = frame;
+ }
+
+ QuicStreamFrame* frame() { return &frame_; }
+
+ private:
+ QuicStreamFrame frame_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor);
+};
+
+class TestSession: public QuicSession {
+ public:
+ TestSession(QuicConnection* connection, bool is_server)
+ : QuicSession(connection, is_server) {
+ }
+
+ MOCK_METHOD1(CreateIncomingReliableStream,
+ ReliableQuicStream*(QuicStreamId id));
+ MOCK_METHOD0(GetCryptoStream, QuicCryptoStream*());
+ MOCK_METHOD0(CreateOutgoingReliableStream, ReliableQuicStream*());
+};
+
+class QuicCryptoServerStreamTest : public ::testing::Test {
+ public:
+ QuicCryptoServerStreamTest()
+ : guid_(1),
+ addr_(),
+ connection_(new PacketSavingConnection(guid_, addr_)),
+ session_(connection_, true),
+ stream_(&session_) {
+ }
+
+ void ConstructHandshakeMessage() {
+ CryptoFramer framer;
+ message_data_.reset(framer.ConstructHandshakeMessage(message_));
+ }
+
+ void CompleteCryptoHandshake() {
+ CryptoTestUtils::HandshakeWithFakeClient(connection_, &stream_);
+ }
+
+ protected:
+ QuicGuid guid_;
+ IPEndPoint addr_;
+ PacketSavingConnection* connection_;
+ TestSession session_;
+ QuicCryptoServerStream stream_;
+ CryptoHandshakeMessage message_;
+ scoped_ptr<QuicData> message_data_;
+};
+
+TEST_F(QuicCryptoServerStreamTest, NotInitiallyConected) {
+ EXPECT_FALSE(stream_.handshake_complete());
+}
+
+TEST_F(QuicCryptoServerStreamTest, ConnectedAfterCHLO) {
+ CompleteCryptoHandshake();
+ EXPECT_TRUE(stream_.handshake_complete());
+}
+
+TEST_F(QuicCryptoServerStreamTest, MessageAfterHandshake) {
+ CompleteCryptoHandshake();
+ EXPECT_CALL(*connection_, SendConnectionClose(
+ QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE));
+ message_.tag = kCHLO;
+ ConstructHandshakeMessage();
+ stream_.ProcessData(message_data_->data(), message_data_->length());
+}
+
+TEST_F(QuicCryptoServerStreamTest, BadMessageType) {
+ message_.tag = kSHLO;
+ ConstructHandshakeMessage();
+ EXPECT_CALL(*connection_, SendConnectionClose(
+ QUIC_INVALID_CRYPTO_MESSAGE_TYPE));
+ stream_.ProcessData(message_data_->data(), message_data_->length());
+}
+
+} // namespace
+} // namespace test
+} // namespace net
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index 3da238b..a9c5e0d 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -3,13 +3,12 @@
// found in the LICENSE file.
#include "net/quic/test_tools/crypto_test_utils.h"
-/*
+
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_crypto_server_stream.h"
#include "net/quic/quic_crypto_stream.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/quic/test_tools/simple_quic_framer.h"
-#include "net/util/ipaddress.h"
namespace net {
namespace test {
@@ -64,7 +63,9 @@ void CryptoTestUtils::HandshakeWithFakeServer(
PacketSavingConnection* client_conn,
QuicCryptoStream* client) {
QuicGuid guid(1);
- SocketAddress addr(IPAddress::Loopback4(), 1);
+ IPAddressNumber ip;
+ CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
+ IPEndPoint addr = IPEndPoint(ip, 1);
PacketSavingConnection* server_conn =
new PacketSavingConnection(guid, addr);
TestSession server_session(server_conn, true);
@@ -81,7 +82,9 @@ void CryptoTestUtils::HandshakeWithFakeClient(
PacketSavingConnection* server_conn,
QuicCryptoStream* server) {
QuicGuid guid(1);
- SocketAddress addr(IPAddress::Loopback4(), 1);
+ IPAddressNumber ip;
+ CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
+ IPEndPoint addr = IPEndPoint(ip, 1);
PacketSavingConnection* client_conn =
new PacketSavingConnection(guid, addr);
TestSession client_session(client_conn, true);
@@ -94,4 +97,3 @@ void CryptoTestUtils::HandshakeWithFakeClient(
}
} // namespace test
} // namespace net
-*/