1 // Copyright (c) 2013 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 "chrome/browser/chromeos/attestation/attestation_ca_client.h"
6 
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/test/bind.h"
10 #include "chrome/test/base/testing_browser_process.h"
11 #include "chromeos/constants/chromeos_switches.h"
12 #include "content/public/test/browser_task_environment.h"
13 #include "net/base/net_errors.h"
14 #include "net/http/http_status_code.h"
15 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
16 #include "services/network/test/test_url_loader_factory.h"
17 #include "services/network/test/test_utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 namespace chromeos {
21 namespace attestation {
22 
23 class AttestationCAClientTest : public ::testing::Test {
24  public:
AttestationCAClientTest()25   AttestationCAClientTest()
26       : test_shared_url_loader_factory_(
27             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
28                 &test_url_loader_factory_)),
29         num_invocations_(0),
30         result_(false) {}
31 
~AttestationCAClientTest()32   ~AttestationCAClientTest() override {}
33 
SetUp()34   void SetUp() override {
35     TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory(
36         test_shared_url_loader_factory_);
37 
38     test_url_loader_factory_.SetInterceptor(base::BindLambdaForTesting(
39         [&](const network::ResourceRequest& request) {
40           last_resource_request_ = request;
41         }));
42   }
43 
DataCallback(bool result,const std::string & data)44   void DataCallback(bool result, const std::string& data) {
45     ++num_invocations_;
46     result_ = result;
47     data_ = data;
48   }
49 
DeleteClientDataCallback(AttestationCAClient * client,bool result,const std::string & data)50   void DeleteClientDataCallback(AttestationCAClient* client,
51                                 bool result,
52                                 const std::string& data) {
53     delete client;
54     DataCallback(result, data);
55   }
56 
57  protected:
CheckURLAndSendResponse(GURL expected_url,net::Error error,int response_code)58   void CheckURLAndSendResponse(GURL expected_url,
59                                net::Error error,
60                                int response_code) {
61     CHECK(test_url_loader_factory_.NumPending() == 1);
62     EXPECT_EQ(expected_url, last_resource_request_.url);
63     std::string response =
64         network::GetUploadData(last_resource_request_) + "_response";
65     test_url_loader_factory_.AddResponse(last_resource_request_.url.spec(),
66                                          response);
67     base::RunLoop().RunUntilIdle();
68   }
69 
SendResponse(net::Error error,net::HttpStatusCode response_code)70   void SendResponse(net::Error error, net::HttpStatusCode response_code) {
71     CHECK(test_url_loader_factory_.NumPending() == 1);
72     auto url_response_head = network::CreateURLResponseHead(response_code);
73     network::URLLoaderCompletionStatus completion_status(error);
74     std::string response =
75         network::GetUploadData(last_resource_request_) + "_response";
76 
77     test_url_loader_factory_.AddResponse(last_resource_request_.url,
78                                          std::move(url_response_head), response,
79                                          completion_status);
80     base::RunLoop().RunUntilIdle();
81   }
82 
83   content::BrowserTaskEnvironment task_environment_;
84 
85   network::TestURLLoaderFactory test_url_loader_factory_;
86   scoped_refptr<network::SharedURLLoaderFactory>
87       test_shared_url_loader_factory_;
88 
89   network::ResourceRequest last_resource_request_;
90 
91   // For use with DataCallback.
92   int num_invocations_;
93   bool result_;
94   std::string data_;
95 };
96 
TEST_F(AttestationCAClientTest,EnrollRequest)97 TEST_F(AttestationCAClientTest, EnrollRequest) {
98   AttestationCAClient client;
99   client.SendEnrollRequest(
100       "enroll", base::BindOnce(&AttestationCAClientTest::DataCallback,
101                                base::Unretained(this)));
102   CheckURLAndSendResponse(GURL("https://chromeos-ca.gstatic.com/enroll"),
103                           net::OK, net::HTTP_OK);
104 
105   EXPECT_EQ(1, num_invocations_);
106   EXPECT_TRUE(result_);
107   EXPECT_EQ("enroll_response", data_);
108 }
109 
TEST_F(AttestationCAClientTest,CertificateRequest)110 TEST_F(AttestationCAClientTest, CertificateRequest) {
111   AttestationCAClient client;
112   client.SendCertificateRequest(
113       "certificate", base::BindOnce(&AttestationCAClientTest::DataCallback,
114                                     base::Unretained(this)));
115   CheckURLAndSendResponse(GURL("https://chromeos-ca.gstatic.com/sign"), net::OK,
116                           net::HTTP_OK);
117 
118   EXPECT_EQ(1, num_invocations_);
119   EXPECT_TRUE(result_);
120   EXPECT_EQ("certificate_response", data_);
121 }
122 
TEST_F(AttestationCAClientTest,CertificateRequestNetworkFailure)123 TEST_F(AttestationCAClientTest, CertificateRequestNetworkFailure) {
124   AttestationCAClient client;
125   client.SendCertificateRequest(
126       "certificate", base::BindOnce(&AttestationCAClientTest::DataCallback,
127                                     base::Unretained(this)));
128   SendResponse(net::ERR_FAILED, net::HTTP_OK);
129 
130   EXPECT_EQ(1, num_invocations_);
131   EXPECT_FALSE(result_);
132   EXPECT_EQ("", data_);
133 }
134 
TEST_F(AttestationCAClientTest,CertificateRequestHttpError)135 TEST_F(AttestationCAClientTest, CertificateRequestHttpError) {
136   AttestationCAClient client;
137   client.SendCertificateRequest(
138       "certificate", base::BindOnce(&AttestationCAClientTest::DataCallback,
139                                     base::Unretained(this)));
140   SendResponse(net::OK, net::HTTP_NOT_FOUND);
141 
142   EXPECT_EQ(1, num_invocations_);
143   EXPECT_FALSE(result_);
144   EXPECT_EQ("", data_);
145 }
146 
TEST_F(AttestationCAClientTest,DeleteOnCallback)147 TEST_F(AttestationCAClientTest, DeleteOnCallback) {
148   AttestationCAClient* client = new AttestationCAClient();
149   client->SendCertificateRequest(
150       "certificate",
151       base::BindOnce(&AttestationCAClientTest::DeleteClientDataCallback,
152                      base::Unretained(this), client));
153   SendResponse(net::OK, net::HTTP_OK);
154 
155   EXPECT_EQ(1, num_invocations_);
156   EXPECT_TRUE(result_);
157   EXPECT_EQ("certificate_response", data_);
158 }
159 
160 class AttestationCAClientAttestationServerTest
161     : public AttestationCAClientTest {};
162 
TEST_F(AttestationCAClientAttestationServerTest,DefaultEnrollRequest)163 TEST_F(AttestationCAClientAttestationServerTest, DefaultEnrollRequest) {
164   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
165       chromeos::switches::kAttestationServer, "default");
166   AttestationCAClient client;
167   client.SendEnrollRequest(
168       "enroll", base::BindOnce(&AttestationCAClientTest::DataCallback,
169                                base::Unretained(this)));
170   CheckURLAndSendResponse(GURL("https://chromeos-ca.gstatic.com/enroll"),
171                           net::OK, net::HTTP_OK);
172 
173   EXPECT_EQ(1, num_invocations_);
174   EXPECT_TRUE(result_);
175   EXPECT_EQ("enroll_response", data_);
176 }
177 
TEST_F(AttestationCAClientAttestationServerTest,DefaultCertificateRequest)178 TEST_F(AttestationCAClientAttestationServerTest, DefaultCertificateRequest) {
179   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
180       chromeos::switches::kAttestationServer, "default");
181   AttestationCAClient client;
182   client.SendCertificateRequest(
183       "certificate", base::BindOnce(&AttestationCAClientTest::DataCallback,
184                                     base::Unretained(this)));
185   CheckURLAndSendResponse(GURL("https://chromeos-ca.gstatic.com/sign"), net::OK,
186                           net::HTTP_OK);
187 
188   EXPECT_EQ(1, num_invocations_);
189   EXPECT_TRUE(result_);
190   EXPECT_EQ("certificate_response", data_);
191 }
192 
TEST_F(AttestationCAClientAttestationServerTest,TestEnrollRequest)193 TEST_F(AttestationCAClientAttestationServerTest, TestEnrollRequest) {
194   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
195       chromeos::switches::kAttestationServer, "test");
196   AttestationCAClient client;
197   client.SendEnrollRequest(
198       "enroll", base::BindOnce(&AttestationCAClientTest::DataCallback,
199                                base::Unretained(this)));
200   CheckURLAndSendResponse(GURL("https://asbestos-qa.corp.google.com/enroll"),
201                           net::OK, net::HTTP_OK);
202 
203   EXPECT_EQ(1, num_invocations_);
204   EXPECT_TRUE(result_);
205   EXPECT_EQ("enroll_response", data_);
206 }
207 
TEST_F(AttestationCAClientAttestationServerTest,TestCertificateRequest)208 TEST_F(AttestationCAClientAttestationServerTest, TestCertificateRequest) {
209   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
210       chromeos::switches::kAttestationServer, "test");
211   AttestationCAClient client;
212   client.SendCertificateRequest(
213       "certificate", base::BindOnce(&AttestationCAClientTest::DataCallback,
214                                     base::Unretained(this)));
215   CheckURLAndSendResponse(GURL("https://asbestos-qa.corp.google.com/sign"),
216                           net::OK, net::HTTP_OK);
217 
218   EXPECT_EQ(1, num_invocations_);
219   EXPECT_TRUE(result_);
220   EXPECT_EQ("certificate_response", data_);
221 }
222 
223 }  // namespace attestation
224 }  // namespace chromeos
225