Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / policy / policy_cert_verifier_browsertest.cc
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/policy/policy_cert_verifier.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/test/test_browser_thread_bundle.h"
16 #include "crypto/nss_util.h"
17 #include "crypto/nss_util_internal.h"
18 #include "net/base/net_log.h"
19 #include "net/base/test_completion_callback.h"
20 #include "net/base/test_data_directory.h"
21 #include "net/cert/cert_trust_anchor_provider.h"
22 #include "net/cert/cert_verify_result.h"
23 #include "net/cert/nss_cert_database.h"
24 #include "net/cert/x509_certificate.h"
25 #include "net/test/cert_test_util.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 namespace policy {
29
30 // This is actually a unit test, but is linked with browser_tests because
31 // importing a certificate into the NSS test database persists for the duration
32 // of a process; since each browser_test runs in a separate process then this
33 // won't affect subsequent tests.
34 // This can be moved to the unittests target once the TODO in ~ScopedTestNSSDB
35 // is fixed.
36 class PolicyCertVerifierTest : public testing::Test {
37  public:
38   PolicyCertVerifierTest() : cert_db_(NULL), trust_anchor_used_(false) {}
39
40   virtual ~PolicyCertVerifierTest() {}
41
42   virtual void SetUp() OVERRIDE {
43     ASSERT_TRUE(test_nssdb_.is_open());
44     cert_db_ = net::NSSCertDatabase::GetInstance();
45
46     cert_verifier_.reset(new PolicyCertVerifier(base::Bind(
47         &PolicyCertVerifierTest::OnTrustAnchorUsed, base::Unretained(this))));
48     cert_verifier_->InitializeOnIOThread(new chromeos::CertVerifyProcChromeOS(
49         crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot())));
50
51     test_ca_cert_ = LoadCertificate("root_ca_cert.pem", net::CA_CERT);
52     ASSERT_TRUE(test_ca_cert_);
53     test_server_cert_ = LoadCertificate("ok_cert.pem", net::SERVER_CERT);
54     ASSERT_TRUE(test_server_cert_);
55     test_ca_cert_list_.push_back(test_ca_cert_);
56   }
57
58   virtual void TearDown() OVERRIDE {
59     // Destroy |cert_verifier_| before destroying the ThreadBundle, otherwise
60     // BrowserThread::CurrentlyOn checks fail.
61     cert_verifier_.reset();
62   }
63
64  protected:
65   int VerifyTestServerCert(const net::TestCompletionCallback& test_callback,
66                            net::CertVerifyResult* verify_result,
67                            net::CertVerifier::RequestHandle* request_handle) {
68     return cert_verifier_->Verify(test_server_cert_.get(),
69                                   "127.0.0.1",
70                                   0,
71                                   NULL,
72                                   verify_result,
73                                   test_callback.callback(),
74                                   request_handle,
75                                   net::BoundNetLog());
76   }
77
78   bool SupportsAdditionalTrustAnchors() {
79     scoped_refptr<net::CertVerifyProc> proc =
80         net::CertVerifyProc::CreateDefault();
81     return proc->SupportsAdditionalTrustAnchors();
82   }
83
84   // Returns whether |cert_verifier| signalled usage of one of the additional
85   // trust anchors (i.e. of |test_ca_cert_|) for the first time or since the
86   // last call of this function.
87   bool WasTrustAnchorUsedAndReset() {
88     base::RunLoop().RunUntilIdle();
89     bool result = trust_anchor_used_;
90     trust_anchor_used_ = false;
91     return result;
92   }
93
94   // |test_ca_cert_| is the issuer of |test_server_cert_|.
95   scoped_refptr<net::X509Certificate> test_ca_cert_;
96   scoped_refptr<net::X509Certificate> test_server_cert_;
97   net::CertificateList test_ca_cert_list_;
98   net::NSSCertDatabase* cert_db_;
99   scoped_ptr<PolicyCertVerifier> cert_verifier_;
100
101  private:
102   void OnTrustAnchorUsed() {
103     trust_anchor_used_ = true;
104   }
105
106   scoped_refptr<net::X509Certificate> LoadCertificate(const std::string& name,
107                                                       net::CertType type) {
108     scoped_refptr<net::X509Certificate> cert =
109         net::ImportCertFromFile(net::GetTestCertsDirectory(), name);
110
111     // No certificate is trusted right after it's loaded.
112     net::NSSCertDatabase::TrustBits trust =
113         cert_db_->GetCertTrust(cert.get(), type);
114     EXPECT_EQ(net::NSSCertDatabase::TRUST_DEFAULT, trust);
115
116     return cert;
117   }
118
119   bool trust_anchor_used_;
120   crypto::ScopedTestNSSDB test_nssdb_;
121   content::TestBrowserThreadBundle thread_bundle_;
122 };
123
124 TEST_F(PolicyCertVerifierTest, VerifyUntrustedCert) {
125   // |test_server_cert_| is untrusted, so Verify() fails.
126   {
127     net::CertVerifyResult verify_result;
128     net::TestCompletionCallback callback;
129     net::CertVerifier::RequestHandle request_handle = NULL;
130     int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
131     ASSERT_EQ(net::ERR_IO_PENDING, error);
132     EXPECT_TRUE(request_handle);
133     error = callback.WaitForResult();
134     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
135   }
136
137   // Issuing the same request again hits the cache. This tests the synchronous
138   // path.
139   {
140     net::CertVerifyResult verify_result;
141     net::TestCompletionCallback callback;
142     net::CertVerifier::RequestHandle request_handle = NULL;
143     int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
144     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
145   }
146
147   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
148 }
149
150 TEST_F(PolicyCertVerifierTest, VerifyTrustedCert) {
151   // Make the database trust |test_ca_cert_|.
152   net::NSSCertDatabase::ImportCertFailureList failure_list;
153   ASSERT_TRUE(cert_db_->ImportCACerts(
154       test_ca_cert_list_, net::NSSCertDatabase::TRUSTED_SSL, &failure_list));
155   ASSERT_TRUE(failure_list.empty());
156
157   // Verify that it is now trusted.
158   net::NSSCertDatabase::TrustBits trust =
159       cert_db_->GetCertTrust(test_ca_cert_.get(), net::CA_CERT);
160   EXPECT_EQ(net::NSSCertDatabase::TRUSTED_SSL, trust);
161
162   // Verify() successfully verifies |test_server_cert_| after it was imported.
163   net::CertVerifyResult verify_result;
164   net::TestCompletionCallback callback;
165   net::CertVerifier::RequestHandle request_handle = NULL;
166   int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
167   ASSERT_EQ(net::ERR_IO_PENDING, error);
168   EXPECT_TRUE(request_handle);
169   error = callback.WaitForResult();
170   EXPECT_EQ(net::OK, error);
171
172   // The additional trust anchors were not used, since the certificate is
173   // trusted from the database.
174   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
175 }
176
177 TEST_F(PolicyCertVerifierTest, VerifyUsingAdditionalTrustAnchor) {
178   ASSERT_TRUE(SupportsAdditionalTrustAnchors());
179
180   // |test_server_cert_| is untrusted, so Verify() fails.
181   {
182     net::CertVerifyResult verify_result;
183     net::TestCompletionCallback callback;
184     net::CertVerifier::RequestHandle request_handle = NULL;
185     int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
186     ASSERT_EQ(net::ERR_IO_PENDING, error);
187     EXPECT_TRUE(request_handle);
188     error = callback.WaitForResult();
189     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
190   }
191   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
192
193   // Verify() again with the additional trust anchors.
194   cert_verifier_->SetTrustAnchors(test_ca_cert_list_);
195   {
196     net::CertVerifyResult verify_result;
197     net::TestCompletionCallback callback;
198     net::CertVerifier::RequestHandle request_handle = NULL;
199     int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
200     ASSERT_EQ(net::ERR_IO_PENDING, error);
201     EXPECT_TRUE(request_handle);
202     error = callback.WaitForResult();
203     EXPECT_EQ(net::OK, error);
204   }
205   EXPECT_TRUE(WasTrustAnchorUsedAndReset());
206
207   // Verify() again with the additional trust anchors will hit the cache.
208   cert_verifier_->SetTrustAnchors(test_ca_cert_list_);
209   {
210     net::CertVerifyResult verify_result;
211     net::TestCompletionCallback callback;
212     net::CertVerifier::RequestHandle request_handle = NULL;
213     int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
214     EXPECT_EQ(net::OK, error);
215   }
216   EXPECT_TRUE(WasTrustAnchorUsedAndReset());
217
218   // Verifying after removing the trust anchors should now fail.
219   cert_verifier_->SetTrustAnchors(net::CertificateList());
220   {
221     net::CertVerifyResult verify_result;
222     net::TestCompletionCallback callback;
223     net::CertVerifier::RequestHandle request_handle = NULL;
224     int error = VerifyTestServerCert(callback, &verify_result, &request_handle);
225     // Note: this hits the cached result from the first Verify() in this test.
226     EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, error);
227   }
228   // The additional trust anchors were reset, thus |cert_verifier_| should not
229   // signal it's usage anymore.
230   EXPECT_FALSE(WasTrustAnchorUsedAndReset());
231 }
232
233 }  // namespace policy