Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chromeos / network / client_cert_resolver_unittest.cc
1 // Copyright 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 #include "chromeos/network/client_cert_resolver.h"
5
6 #include <cert.h>
7 #include <pk11pub.h>
8
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/json/json_reader.h"
12 #include "base/run_loop.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/values.h"
15 #include "chromeos/cert_loader.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "chromeos/dbus/shill_profile_client.h"
18 #include "chromeos/dbus/shill_service_client.h"
19 #include "chromeos/network/managed_network_configuration_handler_impl.h"
20 #include "chromeos/network/network_configuration_handler.h"
21 #include "chromeos/network/network_profile_handler.h"
22 #include "chromeos/network/network_state_handler.h"
23 #include "chromeos/tpm_token_loader.h"
24 #include "crypto/nss_util.h"
25 #include "crypto/nss_util_internal.h"
26 #include "net/base/crypto_module.h"
27 #include "net/base/net_errors.h"
28 #include "net/base/test_data_directory.h"
29 #include "net/cert/nss_cert_database_chromeos.h"
30 #include "net/cert/x509_certificate.h"
31 #include "net/test/cert_test_util.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 #include "third_party/cros_system_api/dbus/service_constants.h"
34
35 namespace chromeos {
36
37 namespace {
38
39 const char* kWifiStub = "wifi_stub";
40 const char* kWifiSSID = "wifi_ssid";
41 const char* kUserProfilePath = "user_profile";
42 const char* kUserHash = "user_hash";
43
44 }  // namespace
45
46 class ClientCertResolverTest : public testing::Test {
47  public:
48   ClientCertResolverTest() : service_test_(NULL),
49                              profile_test_(NULL),
50                              user_(kUserHash) {
51   }
52   virtual ~ClientCertResolverTest() {}
53
54   virtual void SetUp() OVERRIDE {
55     // Initialize NSS db for the user.
56     ASSERT_TRUE(user_.constructed_successfully());
57     user_.FinishInit();
58     private_slot_ = crypto::GetPrivateSlotForChromeOSUser(
59         user_.username_hash(),
60         base::Callback<void(crypto::ScopedPK11Slot)>());
61     ASSERT_TRUE(private_slot_.get());
62     test_nssdb_.reset(new net::NSSCertDatabaseChromeOS(
63         crypto::GetPublicSlotForChromeOSUser(user_.username_hash()),
64         crypto::GetPrivateSlotForChromeOSUser(
65             user_.username_hash(),
66             base::Callback<void(crypto::ScopedPK11Slot)>())));
67     test_nssdb_->SetSlowTaskRunnerForTest(message_loop_.message_loop_proxy());
68
69     DBusThreadManager::InitializeWithStub();
70     service_test_ =
71         DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
72     profile_test_ =
73         DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
74     base::RunLoop().RunUntilIdle();
75     service_test_->ClearServices();
76     base::RunLoop().RunUntilIdle();
77
78     TPMTokenLoader::InitializeForTest();
79
80     CertLoader::Initialize();
81     CertLoader* cert_loader_ = CertLoader::Get();
82     cert_loader_->force_hardware_backed_for_test();
83     cert_loader_->StartWithNSSDB(test_nssdb_.get());
84   }
85
86   virtual void TearDown() OVERRIDE {
87     client_cert_resolver_.reset();
88     managed_config_handler_.reset();
89     network_config_handler_.reset();
90     network_profile_handler_.reset();
91     network_state_handler_.reset();
92     CertLoader::Shutdown();
93     TPMTokenLoader::Shutdown();
94     DBusThreadManager::Shutdown();
95     CleanupSlotContents();
96   }
97
98  protected:
99   // Imports a CA cert (stored as PEM in test_ca_cert_pem_) and a client
100   // certificate signed by that CA. Its PKCS#11 ID is stored in
101   // |test_pkcs11_id_|.
102   void SetupTestCerts() {
103     // Import a CA cert.
104     net::CertificateList ca_cert_list =
105         net::CreateCertificateListFromFile(net::GetTestCertsDirectory(),
106                                            "websocket_cacert.pem",
107                                            net::X509Certificate::FORMAT_AUTO);
108     ASSERT_TRUE(!ca_cert_list.empty());
109     net::NSSCertDatabase::ImportCertFailureList failures;
110     EXPECT_TRUE(test_nssdb_->ImportCACerts(
111         ca_cert_list, net::NSSCertDatabase::TRUST_DEFAULT, &failures));
112     ASSERT_TRUE(failures.empty()) << net::ErrorToString(failures[0].net_error);
113
114     net::X509Certificate::GetPEMEncoded(ca_cert_list[0]->os_cert_handle(),
115                                         &test_ca_cert_pem_);
116     ASSERT_TRUE(!test_ca_cert_pem_.empty());
117
118     // Import a client cert signed by that CA.
119     std::string pkcs12_data;
120     ASSERT_TRUE(base::ReadFileToString(
121         net::GetTestCertsDirectory().Append("websocket_client_cert.p12"),
122         &pkcs12_data));
123
124     net::CertificateList client_cert_list;
125     scoped_refptr<net::CryptoModule> module(
126         net::CryptoModule::CreateFromHandle(private_slot_.get()));
127     ASSERT_EQ(
128         net::OK,
129         test_nssdb_->ImportFromPKCS12(
130             module, pkcs12_data, base::string16(), false, &client_cert_list));
131     ASSERT_TRUE(!client_cert_list.empty());
132     test_pkcs11_id_ = CertLoader::GetPkcs11IdForCert(*client_cert_list[0]);
133     ASSERT_TRUE(!test_pkcs11_id_.empty());
134   }
135
136   void SetupNetworkHandlers() {
137     network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
138     network_profile_handler_.reset(new NetworkProfileHandler());
139     network_config_handler_.reset(new NetworkConfigurationHandler());
140     managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl());
141     client_cert_resolver_.reset(new ClientCertResolver());
142
143     network_profile_handler_->Init(network_state_handler_.get());
144     network_config_handler_->Init(network_state_handler_.get());
145     managed_config_handler_->Init(network_state_handler_.get(),
146                                   network_profile_handler_.get(),
147                                   network_config_handler_.get());
148     client_cert_resolver_->Init(network_state_handler_.get(),
149                                 managed_config_handler_.get());
150     client_cert_resolver_->SetSlowTaskRunnerForTest(
151         message_loop_.message_loop_proxy());
152
153     profile_test_->AddProfile(kUserProfilePath, kUserHash);
154   }
155
156   void SetupWifi() {
157     const bool add_to_visible = true;
158     const bool add_to_watchlist = true;
159     service_test_->AddService(kWifiStub,
160                               kWifiSSID,
161                               shill::kTypeWifi,
162                               shill::kStateOnline,
163                               add_to_visible,
164                               add_to_watchlist);
165     service_test_->SetServiceProperty(
166         kWifiStub, shill::kGuidProperty, base::StringValue(kWifiStub));
167
168     profile_test_->AddService(kUserProfilePath, kWifiStub);
169   }
170
171   // Setup a policy with a certificate pattern that matches any client cert that
172   // is signed by the test CA cert (stored in |test_ca_cert_pem_|). In
173   // particular it will match the test client cert.
174   void SetupPolicy() {
175     const char* kTestPolicyTemplate =
176         "[ { \"GUID\": \"wifi_stub\","
177         "    \"Name\": \"wifi_stub\","
178         "    \"Type\": \"WiFi\","
179         "    \"WiFi\": {"
180         "      \"Security\": \"WPA-EAP\","
181         "      \"SSID\": \"wifi_ssid\","
182         "      \"EAP\": {"
183         "        \"Outer\": \"EAP-TLS\","
184         "        \"ClientCertType\": \"Pattern\","
185         "        \"ClientCertPattern\": {"
186         "          \"IssuerCAPEMs\": [ \"%s\" ]"
187         "        }"
188         "      }"
189         "    }"
190         "} ]";
191     std::string policy_json =
192         base::StringPrintf(kTestPolicyTemplate, test_ca_cert_pem_.c_str());
193
194     std::string error;
195     scoped_ptr<base::Value> policy_value(base::JSONReader::ReadAndReturnError(
196         policy_json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
197     ASSERT_TRUE(policy_value) << error;
198
199     base::ListValue* policy = NULL;
200     ASSERT_TRUE(policy_value->GetAsList(&policy));
201
202     managed_config_handler_->SetPolicy(
203         onc::ONC_SOURCE_USER_POLICY,
204         kUserHash,
205         *policy,
206         base::DictionaryValue() /* no global network config */);
207   }
208
209   void GetClientCertProperties(std::string* pkcs11_id) {
210     pkcs11_id->clear();
211     const base::DictionaryValue* properties =
212         service_test_->GetServiceProperties(kWifiStub);
213     if (!properties)
214       return;
215     properties->GetStringWithoutPathExpansion(shill::kEapCertIdProperty,
216                                               pkcs11_id);
217   }
218
219   ShillServiceClient::TestInterface* service_test_;
220   ShillProfileClient::TestInterface* profile_test_;
221   std::string test_pkcs11_id_;
222   scoped_refptr<net::X509Certificate> test_ca_cert_;
223   std::string test_ca_cert_pem_;
224   base::MessageLoop message_loop_;
225
226  private:
227   void CleanupSlotContents() {
228     CERTCertList* cert_list = PK11_ListCertsInSlot(private_slot_.get());
229     for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
230          !CERT_LIST_END(node, cert_list);
231          node = CERT_LIST_NEXT(node)) {
232       scoped_refptr<net::X509Certificate> cert(
233           net::X509Certificate::CreateFromHandle(
234               node->cert, net::X509Certificate::OSCertHandles()));
235       test_nssdb_->DeleteCertAndKey(cert.get());
236     }
237     CERT_DestroyCertList(cert_list);
238   }
239
240   scoped_ptr<NetworkStateHandler> network_state_handler_;
241   scoped_ptr<NetworkProfileHandler> network_profile_handler_;
242   scoped_ptr<NetworkConfigurationHandler> network_config_handler_;
243   scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_;
244   scoped_ptr<ClientCertResolver> client_cert_resolver_;
245   crypto::ScopedTestNSSChromeOSUser user_;
246   scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_;
247   crypto::ScopedPK11Slot private_slot_;
248
249   DISALLOW_COPY_AND_ASSIGN(ClientCertResolverTest);
250 };
251
252 TEST_F(ClientCertResolverTest, NoMatchingCertificates) {
253   SetupNetworkHandlers();
254   SetupPolicy();
255   base::RunLoop().RunUntilIdle();
256
257   SetupWifi();
258   base::RunLoop().RunUntilIdle();
259
260   // Verify that no client certificate was configured.
261   std::string pkcs11_id;
262   GetClientCertProperties(&pkcs11_id);
263   EXPECT_TRUE(pkcs11_id.empty());
264 }
265
266 TEST_F(ClientCertResolverTest, ResolveOnInitialization) {
267   SetupTestCerts();
268   SetupNetworkHandlers();
269   SetupPolicy();
270   base::RunLoop().RunUntilIdle();
271
272   SetupWifi();
273   base::RunLoop().RunUntilIdle();
274
275   // Verify that the resolver positively matched the pattern in the policy with
276   // the test client cert and configured the network.
277   std::string pkcs11_id;
278   GetClientCertProperties(&pkcs11_id);
279   EXPECT_EQ(test_pkcs11_id_, pkcs11_id);
280 }
281
282 TEST_F(ClientCertResolverTest, ResolveAfterPolicyApplication) {
283   SetupTestCerts();
284   SetupNetworkHandlers();
285   base::RunLoop().RunUntilIdle();
286
287   // The policy will trigger the creation of a new wifi service.
288   SetupPolicy();
289   base::RunLoop().RunUntilIdle();
290
291   // Verify that the resolver positively matched the pattern in the policy with
292   // the test client cert and configured the network.
293   std::string pkcs11_id;
294   GetClientCertProperties(&pkcs11_id);
295   EXPECT_EQ(test_pkcs11_id_, pkcs11_id);
296 }
297
298 }  // namespace chromeos