root/net/ssl/client_cert_store_chromeos_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SelectClientCerts
  2. ImportCertForUser
  3. TEST_F
  4. TEST_F
  5. TEST_F

// Copyright 2013 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/ssl/client_cert_store_chromeos.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "net/cert/nss_cert_database.h"
#include "net/ssl/client_cert_store_unittest-inl.h"

namespace net {

class ClientCertStoreChromeOSTestDelegate {
 public:
  ClientCertStoreChromeOSTestDelegate()
      : store_("usernamehash",
               ClientCertStoreChromeOS::PasswordDelegateFactory()) {
    store_.InitForTesting(
        crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()),
        crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()));
  }

  bool SelectClientCerts(const CertificateList& input_certs,
                         const SSLCertRequestInfo& cert_request_info,
                         CertificateList* selected_certs) {
    return store_.SelectClientCertsForTesting(
        input_certs, cert_request_info, selected_certs);
  }

 private:
  ClientCertStoreChromeOS store_;
};

class ClientCertStoreChromeOSTest : public ::testing::Test {
 public:
  scoped_refptr<X509Certificate> ImportCertForUser(
      const std::string& username_hash,
      const std::string& filename,
      const std::string& password) {
    crypto::ScopedPK11Slot slot(
        crypto::GetPublicSlotForChromeOSUser(username_hash));
    EXPECT_TRUE(slot.get());
    if (!slot.get())
      return NULL;

    net::CertificateList cert_list;

    base::FilePath p12_path = GetTestCertsDirectory().AppendASCII(filename);
    std::string p12_data;
    if (!base::ReadFileToString(p12_path, &p12_data)) {
      EXPECT_TRUE(false);
      return NULL;
    }

    scoped_refptr<net::CryptoModule> module(
        net::CryptoModule::CreateFromHandle(slot.get()));
    int rv = NSSCertDatabase::GetInstance()->ImportFromPKCS12(
        module.get(), p12_data, base::UTF8ToUTF16(password), false, &cert_list);

    EXPECT_EQ(0, rv);
    EXPECT_EQ(1U, cert_list.size());
    if (rv || cert_list.size() != 1)
      return NULL;

    return cert_list[0];
  }
};

// TODO(mattm): Do better testing of cert_authorities matching below. Update
// net/data/ssl/scripts/generate-client-certificates.sh so that it actually
// saves the .p12 files, and regenerate them.

TEST_F(ClientCertStoreChromeOSTest, WaitForNSSInit) {
  crypto::ScopedTestNSSChromeOSUser user("scopeduser");
  ASSERT_TRUE(user.constructed_successfully());
  ClientCertStoreChromeOS store(
      user.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory());
  scoped_refptr<X509Certificate> cert_1(
      ImportCertForUser(user.username_hash(), "client.p12", "12345"));
  scoped_refptr<X509Certificate> cert_2(
      ImportCertForUser(user.username_hash(), "websocket_client_cert.p12", ""));

  std::vector<std::string> authority_1(
      1,
      std::string(reinterpret_cast<const char*>(kAuthority1DN),
                  sizeof(kAuthority1DN)));
  scoped_refptr<SSLCertRequestInfo> request_1(new SSLCertRequestInfo());
  request_1->cert_authorities = authority_1;

  scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());

  base::RunLoop run_loop_1;
  base::RunLoop run_loop_all;
  store.GetClientCerts(
      *request_1, &request_1->client_certs, run_loop_1.QuitClosure());
  store.GetClientCerts(
      *request_all, &request_all->client_certs, run_loop_all.QuitClosure());

  // Callbacks won't be run until nss_util init finishes for the user.
  user.FinishInit();

  run_loop_1.Run();
  run_loop_all.Run();

  ASSERT_EQ(0u, request_1->client_certs.size());
  ASSERT_EQ(2u, request_all->client_certs.size());
}

TEST_F(ClientCertStoreChromeOSTest, NSSAlreadyInitialized) {
  crypto::ScopedTestNSSChromeOSUser user("scopeduser");
  ASSERT_TRUE(user.constructed_successfully());
  user.FinishInit();

  ClientCertStoreChromeOS store(
      user.username_hash(), ClientCertStoreChromeOS::PasswordDelegateFactory());
  scoped_refptr<X509Certificate> cert_1(
      ImportCertForUser(user.username_hash(), "client.p12", "12345"));
  scoped_refptr<X509Certificate> cert_2(
      ImportCertForUser(user.username_hash(), "websocket_client_cert.p12", ""));

  std::vector<std::string> authority_1(
      1,
      std::string(reinterpret_cast<const char*>(kAuthority1DN),
                  sizeof(kAuthority1DN)));
  scoped_refptr<SSLCertRequestInfo> request_1(new SSLCertRequestInfo());
  request_1->cert_authorities = authority_1;

  scoped_refptr<SSLCertRequestInfo> request_all(new SSLCertRequestInfo());

  base::RunLoop run_loop_1;
  base::RunLoop run_loop_all;
  store.GetClientCerts(
      *request_1, &request_1->client_certs, run_loop_1.QuitClosure());
  store.GetClientCerts(
      *request_all, &request_all->client_certs, run_loop_all.QuitClosure());

  run_loop_1.Run();
  run_loop_all.Run();

  ASSERT_EQ(0u, request_1->client_certs.size());
  ASSERT_EQ(2u, request_all->client_certs.size());
}

TEST_F(ClientCertStoreChromeOSTest, TwoUsers) {
  crypto::ScopedTestNSSChromeOSUser user1("scopeduser1");
  ASSERT_TRUE(user1.constructed_successfully());
  crypto::ScopedTestNSSChromeOSUser user2("scopeduser2");
  ASSERT_TRUE(user2.constructed_successfully());
  ClientCertStoreChromeOS store1(
      user1.username_hash(),
      ClientCertStoreChromeOS::PasswordDelegateFactory());
  ClientCertStoreChromeOS store2(
      user2.username_hash(),
      ClientCertStoreChromeOS::PasswordDelegateFactory());
  scoped_refptr<X509Certificate> cert_1(
      ImportCertForUser(user1.username_hash(), "client.p12", "12345"));
  scoped_refptr<X509Certificate> cert_2(ImportCertForUser(
      user2.username_hash(), "websocket_client_cert.p12", ""));

  scoped_refptr<SSLCertRequestInfo> request_1(new SSLCertRequestInfo());
  scoped_refptr<SSLCertRequestInfo> request_2(new SSLCertRequestInfo());

  base::RunLoop run_loop_1;
  base::RunLoop run_loop_2;
  store1.GetClientCerts(
      *request_1, &request_1->client_certs, run_loop_1.QuitClosure());
  store2.GetClientCerts(
      *request_2, &request_2->client_certs, run_loop_2.QuitClosure());

  // Callbacks won't be run until nss_util init finishes for the user.
  user1.FinishInit();
  user2.FinishInit();

  run_loop_1.Run();
  run_loop_2.Run();

  ASSERT_EQ(1u, request_1->client_certs.size());
  EXPECT_TRUE(cert_1->Equals(request_1->client_certs[0]));
  // TODO(mattm): Request for second user will have zero results due to
  // crbug.com/315285.  Update the test once that is fixed.
}

}  // namespace net

/* [<][>][^][v][top][bottom][index][help] */