1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdio.h>
6
7 #include "cast/common/certificate/cast_trust_store.h"
8 #include "cast/common/certificate/testing/test_helpers.h"
9 #include "cast/common/channel/proto/cast_channel.pb.h"
10 #include "cast/common/channel/testing/fake_cast_socket.h"
11 #include "cast/common/channel/testing/mock_socket_error_handler.h"
12 #include "cast/common/channel/virtual_connection_manager.h"
13 #include "cast/common/channel/virtual_connection_router.h"
14 #include "cast/common/public/cast_socket.h"
15 #include "cast/receiver/channel/device_auth_namespace_handler.h"
16 #include "cast/receiver/channel/static_credentials.h"
17 #include "cast/receiver/channel/testing/device_auth_test_helpers.h"
18 #include "cast/sender/channel/cast_auth_util.h"
19 #include "cast/sender/channel/message_util.h"
20 #include "gtest/gtest.h"
21 #include "platform/test/paths.h"
22 #include "testing/util/read_file.h"
23
24 namespace openscreen {
25 namespace cast {
26 namespace {
27
28 using ::cast::channel::CastMessage;
29 using ::cast::channel::DeviceAuthMessage;
30
31 using ::testing::_;
32 using ::testing::Invoke;
33
GetSpecificTestDataPath()34 const std::string& GetSpecificTestDataPath() {
35 static std::string data_path = GetTestDataPath() + "cast/receiver/channel/";
36 return data_path;
37 }
38
39 class DeviceAuthTest : public ::testing::Test {
40 public:
SetUp()41 void SetUp() override {
42 socket_ = fake_cast_socket_pair_.socket.get();
43 router_.TakeSocket(&mock_error_handler_,
44 std::move(fake_cast_socket_pair_.socket));
45 router_.AddHandlerForLocalId(kPlatformReceiverId, &auth_handler_);
46 }
47
48 protected:
RunAuthTest(std::string serialized_crl,TrustStore * fake_crl_trust_store,bool should_succeed=true,bool record_this_test=false)49 void RunAuthTest(std::string serialized_crl,
50 TrustStore* fake_crl_trust_store,
51 bool should_succeed = true,
52 bool record_this_test = false) {
53 bssl::UniquePtr<X509> parsed_cert;
54 TrustStore fake_trust_store;
55 InitStaticCredentialsFromFiles(
56 &creds_, &parsed_cert, &fake_trust_store, data_path_ + "device_key.pem",
57 data_path_ + "device_chain.pem", data_path_ + "device_tls.pem");
58 creds_.device_creds.serialized_crl = std::move(serialized_crl);
59
60 // Send an auth challenge. |auth_handler_| will automatically respond
61 // via |router_| and we will catch the result in |challenge_reply|.
62 AuthContext auth_context = AuthContext::Create();
63 CastMessage auth_challenge = CreateAuthChallengeMessage(auth_context);
64 if (record_this_test) {
65 std::string output;
66 DeviceAuthMessage auth_message;
67 ASSERT_EQ(auth_challenge.payload_type(),
68 ::cast::channel::CastMessage_PayloadType_BINARY);
69 ASSERT_TRUE(
70 auth_message.ParseFromString(auth_challenge.payload_binary()));
71 ASSERT_TRUE(auth_message.has_challenge());
72 ASSERT_FALSE(auth_message.has_response());
73 ASSERT_FALSE(auth_message.has_error());
74 ASSERT_TRUE(auth_challenge.SerializeToString(&output));
75
76 const std::string pb_path = data_path_ + "auth_challenge.pb";
77 FILE* fd = fopen(pb_path.c_str(), "wb");
78 ASSERT_TRUE(fd);
79 ASSERT_EQ(fwrite(output.data(), 1, output.size(), fd), output.size());
80 fclose(fd);
81 }
82 CastMessage challenge_reply;
83 EXPECT_CALL(fake_cast_socket_pair_.mock_peer_client, OnMessage(_, _))
84 .WillOnce(
85 Invoke([&challenge_reply](CastSocket* socket, CastMessage message) {
86 challenge_reply = std::move(message);
87 }));
88 ASSERT_TRUE(
89 fake_cast_socket_pair_.peer_socket->Send(std::move(auth_challenge))
90 .ok());
91
92 if (record_this_test) {
93 std::string output;
94 DeviceAuthMessage auth_message;
95 ASSERT_EQ(challenge_reply.payload_type(),
96 ::cast::channel::CastMessage_PayloadType_BINARY);
97 ASSERT_TRUE(
98 auth_message.ParseFromString(challenge_reply.payload_binary()));
99 ASSERT_TRUE(auth_message.has_response());
100 ASSERT_FALSE(auth_message.has_challenge());
101 ASSERT_FALSE(auth_message.has_error());
102 ASSERT_TRUE(auth_message.response().SerializeToString(&output));
103
104 const std::string pb_path = data_path_ + "auth_response.pb";
105 FILE* fd = fopen(pb_path.c_str(), "wb");
106 ASSERT_TRUE(fd);
107 ASSERT_EQ(fwrite(output.data(), 1, output.size(), fd), output.size());
108 fclose(fd);
109 }
110
111 DateTime December2019 = {};
112 December2019.year = 2019;
113 December2019.month = 12;
114 December2019.day = 17;
115 const ErrorOr<CastDeviceCertPolicy> error_or_policy =
116 AuthenticateChallengeReplyForTest(
117 challenge_reply, parsed_cert.get(), auth_context,
118 fake_crl_trust_store ? CRLPolicy::kCrlRequired
119 : CRLPolicy::kCrlOptional,
120 &fake_trust_store, fake_crl_trust_store, December2019);
121 EXPECT_EQ(error_or_policy.is_value(), should_succeed);
122 }
123
124 const std::string& data_path_{GetSpecificTestDataPath()};
125 FakeCastSocketPair fake_cast_socket_pair_;
126 MockSocketErrorHandler mock_error_handler_;
127 CastSocket* socket_;
128
129 StaticCredentialsProvider creds_;
130 VirtualConnectionManager manager_;
131 VirtualConnectionRouter router_{&manager_};
132 DeviceAuthNamespaceHandler auth_handler_{&creds_};
133 };
134
TEST_F(DeviceAuthTest,MANUAL_SerializeTestData)135 TEST_F(DeviceAuthTest, MANUAL_SerializeTestData) {
136 if (::testing::GTEST_FLAG(filter) ==
137 "DeviceAuthTest.MANUAL_SerializeTestData") {
138 RunAuthTest(std::string(), nullptr, true, true);
139 }
140 }
141
TEST_F(DeviceAuthTest,AuthIntegration)142 TEST_F(DeviceAuthTest, AuthIntegration) {
143 RunAuthTest(std::string(), nullptr);
144 }
145
TEST_F(DeviceAuthTest,GoodCrl)146 TEST_F(DeviceAuthTest, GoodCrl) {
147 auto fake_crl_trust_store =
148 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
149 RunAuthTest(ReadEntireFileToString(data_path_ + "good_crl.pb"),
150 &fake_crl_trust_store);
151 }
152
TEST_F(DeviceAuthTest,InvalidCrlTime)153 TEST_F(DeviceAuthTest, InvalidCrlTime) {
154 auto fake_crl_trust_store =
155 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
156 RunAuthTest(ReadEntireFileToString(data_path_ + "invalid_time_crl.pb"),
157 &fake_crl_trust_store, false);
158 }
159
TEST_F(DeviceAuthTest,IssuerRevoked)160 TEST_F(DeviceAuthTest, IssuerRevoked) {
161 auto fake_crl_trust_store =
162 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
163 RunAuthTest(ReadEntireFileToString(data_path_ + "issuer_revoked_crl.pb"),
164 &fake_crl_trust_store, false);
165 }
166
TEST_F(DeviceAuthTest,DeviceRevoked)167 TEST_F(DeviceAuthTest, DeviceRevoked) {
168 auto fake_crl_trust_store =
169 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
170 RunAuthTest(ReadEntireFileToString(data_path_ + "device_revoked_crl.pb"),
171 &fake_crl_trust_store, false);
172 }
173
TEST_F(DeviceAuthTest,IssuerSerialRevoked)174 TEST_F(DeviceAuthTest, IssuerSerialRevoked) {
175 auto fake_crl_trust_store =
176 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
177 RunAuthTest(
178 ReadEntireFileToString(data_path_ + "issuer_serial_revoked_crl.pb"),
179 &fake_crl_trust_store, false);
180 }
181
TEST_F(DeviceAuthTest,DeviceSerialRevoked)182 TEST_F(DeviceAuthTest, DeviceSerialRevoked) {
183 auto fake_crl_trust_store =
184 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
185 RunAuthTest(
186 ReadEntireFileToString(data_path_ + "device_serial_revoked_crl.pb"),
187 &fake_crl_trust_store, false);
188 }
189
TEST_F(DeviceAuthTest,BadCrlSignerCert)190 TEST_F(DeviceAuthTest, BadCrlSignerCert) {
191 auto fake_crl_trust_store =
192 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
193 RunAuthTest(ReadEntireFileToString(data_path_ + "bad_signer_cert_crl.pb"),
194 &fake_crl_trust_store, false);
195 }
196
TEST_F(DeviceAuthTest,BadCrlSignature)197 TEST_F(DeviceAuthTest, BadCrlSignature) {
198 auto fake_crl_trust_store =
199 TrustStore::CreateInstanceFromPemFile(data_path_ + "crl_root.pem");
200 RunAuthTest(ReadEntireFileToString(data_path_ + "bad_signature_crl.pb"),
201 &fake_crl_trust_store, false);
202 }
203
204 } // namespace
205 } // namespace cast
206 } // namespace openscreen
207