190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/ocsp/nss_ocsp.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <string>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/file_util.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/file_path.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/ref_counted.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/net_errors.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/test_completion_callback.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/test_data_directory.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/cert_status_flags.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/cert_verifier.h"
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/cert_verify_proc.h"
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/cert_verify_proc_nss.h"
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/cert_verify_result.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/multi_threaded_cert_verifier.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/test_root_certs.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/cert/x509_certificate.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/test/cert_test_util.h"
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/url_request/url_request_filter.h"
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "net/url_request/url_request_interceptor.h"
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/url_request/url_request_test_job.h"
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/url_request/url_request_test_util.h"
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace net {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Matches the caIssuers hostname from the generated certificate.
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kAiaHost[] = "aia-test.invalid";
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Returning a single DER-encoded cert, so the mime-type must be
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// application/pkix-cert per RFC 5280.
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const char kAiaHeaders[] = "HTTP/1.1 200 OK\0"
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           "Content-type: application/pkix-cert\0"
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           "\0";
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AiaResponseHandler : public net::URLRequestInterceptor {
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  AiaResponseHandler(const std::string& headers, const std::string& cert_data)
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : headers_(headers), cert_data_(cert_data), request_count_(0) {}
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~AiaResponseHandler() {}
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // net::URLRequestInterceptor implementation:
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual net::URLRequestJob* MaybeInterceptRequest(
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      net::URLRequest* request,
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      net::NetworkDelegate* network_delegate) const OVERRIDE {
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ++const_cast<AiaResponseHandler*>(this)->request_count_;
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return new net::URLRequestTestJob(
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        request, network_delegate, headers_, cert_data_, true);
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int request_count() const { return request_count_; }
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string headers_;
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string cert_data_;
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int request_count_;
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AiaResponseHandler);
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NssHttpTest : public ::testing::Test {
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NssHttpTest()
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      : context_(false),
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        handler_(NULL),
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        verify_proc_(new CertVerifyProcNSS),
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        verifier_(new MultiThreadedCertVerifier(verify_proc_.get())) {}
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~NssHttpTest() {}
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void SetUp() {
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::string file_contents;
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ASSERT_TRUE(base::ReadFileToString(
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        GetTestCertsDirectory().AppendASCII("aia-intermediate.der"),
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        &file_contents));
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_FALSE(file_contents.empty());
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Ownership of |handler| is transferred to the URLRequestFilter, but
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // hold onto the original pointer in order to access |request_count()|.
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<AiaResponseHandler> handler(
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        new AiaResponseHandler(kAiaHeaders, file_contents));
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    handler_ = handler.get();
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    URLRequestFilter::GetInstance()->AddHostnameInterceptor(
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        "http",
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        kAiaHost,
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        handler.PassAs<URLRequestInterceptor>());
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SetURLRequestContextForNSSHttpIO(&context_);
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    EnsureNSSHttpIOInit();
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual void TearDown() {
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ShutdownNSSHttpIO();
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (handler_)
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", kAiaHost);
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CertVerifier* verifier() const {
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return verifier_.get();
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int request_count() const {
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return handler_->request_count();
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) protected:
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const CertificateList empty_cert_list_;
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TestURLRequestContext context_;
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  AiaResponseHandler* handler_;
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<CertVerifyProc> verify_proc_;
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<CertVerifier> verifier_;
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Tests that when using NSS to verify certificates, and IO is enabled,
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// that a request to fetch missing intermediate certificates is
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// made successfully.
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)TEST_F(NssHttpTest, TestAia) {
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<X509Certificate> test_cert(
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ImportCertFromFile(GetTestCertsDirectory(), "aia-cert.pem"));
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(test_cert.get());
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<X509Certificate> test_root(
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ImportCertFromFile(GetTestCertsDirectory(), "aia-root.pem"));
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(test_root.get());
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ScopedTestRoot scoped_root(test_root.get());
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CertVerifyResult verify_result;
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  TestCompletionCallback test_callback;
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  CertVerifier::RequestHandle request_handle;
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int flags = CertVerifier::VERIFY_CERT_IO_ENABLED;
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int error = verifier()->Verify(test_cert.get(),
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 "aia-host.invalid",
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 flags,
149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 NULL,
150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 &verify_result,
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 test_callback.callback(),
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 &request_handle,
153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 BoundNetLog());
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, error);
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  error = test_callback.WaitForResult();
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_EQ(OK, error);
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Ensure that NSS made an AIA request for the missing intermediate.
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_LT(0, request_count());
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace net
165