// Copyright 2014 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/channel_id_service.h"

#include <algorithm>
#include <limits>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/task_runner.h"
#include "crypto/ec_private_key.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "url/gurl.h"

#if !defined(USE_OPENSSL)
#include <private/pprthred.h>  // PR_DetachThread
#endif

namespace net {

namespace {

const int kValidityPeriodInDays = 365;
// When we check the system time, we add this many days to the end of the check
// so the result will still hold even after chrome has been running for a
// while.
const int kSystemTimeValidityBufferInDays = 90;

// Used by the GetDomainBoundCertResult histogram to record the final
// outcome of each GetChannelID or GetOrCreateChannelID call.
// Do not re-use values.
enum GetChannelIDResult {
  // Synchronously found and returned an existing domain bound cert.
  SYNC_SUCCESS = 0,
  // Retrieved or generated and returned a domain bound cert asynchronously.
  ASYNC_SUCCESS = 1,
  // Retrieval/generation request was cancelled before the cert generation
  // completed.
  ASYNC_CANCELLED = 2,
  // Cert generation failed.
  ASYNC_FAILURE_KEYGEN = 3,
  ASYNC_FAILURE_CREATE_CERT = 4,
  ASYNC_FAILURE_EXPORT_KEY = 5,
  ASYNC_FAILURE_UNKNOWN = 6,
  // GetChannelID or GetOrCreateChannelID was called with
  // invalid arguments.
  INVALID_ARGUMENT = 7,
  // We don't support any of the cert types the server requested.
  UNSUPPORTED_TYPE = 8,
  // Server asked for a different type of certs while we were generating one.
  TYPE_MISMATCH = 9,
  // Couldn't start a worker to generate a cert.
  WORKER_FAILURE = 10,
  GET_CHANNEL_ID_RESULT_MAX
};

void RecordGetChannelIDResult(GetChannelIDResult result) {
  UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.GetDomainBoundCertResult", result,
                            GET_CHANNEL_ID_RESULT_MAX);
}

void RecordGetChannelIDTime(base::TimeDelta request_time) {
  UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GetCertTime",
                             request_time,
                             base::TimeDelta::FromMilliseconds(1),
                             base::TimeDelta::FromMinutes(5),
                             50);
}

// On success, returns a ChannelID object and sets |*error| to OK.
// Otherwise, returns NULL, and |*error| will be set to a net error code.
// |serial_number| is passed in because base::RandInt cannot be called from an
// unjoined thread, due to relying on a non-leaked LazyInstance
scoped_ptr<ChannelIDStore::ChannelID> GenerateChannelID(
    const std::string& server_identifier,
    uint32 serial_number,
    int* error) {
  scoped_ptr<ChannelIDStore::ChannelID> result;

  base::TimeTicks start = base::TimeTicks::Now();
  base::Time not_valid_before = base::Time::Now();
  base::Time not_valid_after =
      not_valid_before + base::TimeDelta::FromDays(kValidityPeriodInDays);
  std::string der_cert;
  std::vector<uint8> private_key_info;
  scoped_ptr<crypto::ECPrivateKey> key;
  if (!x509_util::CreateKeyAndChannelIDEC(server_identifier,
                                          serial_number,
                                          not_valid_before,
                                          not_valid_after,
                                          &key,
                                          &der_cert)) {
    DLOG(ERROR) << "Unable to create x509 cert for client";
    *error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED;
    return result.Pass();
  }

  if (!key->ExportEncryptedPrivateKey(ChannelIDService::kEPKIPassword,
                                      1, &private_key_info)) {
    DLOG(ERROR) << "Unable to export private key";
    *error = ERR_PRIVATE_KEY_EXPORT_FAILED;
    return result.Pass();
  }

  // TODO(rkn): Perhaps ExportPrivateKey should be changed to output a
  // std::string* to prevent this copying.
  std::string key_out(private_key_info.begin(), private_key_info.end());

  result.reset(new ChannelIDStore::ChannelID(
      server_identifier,
      not_valid_before,
      not_valid_after,
      key_out,
      der_cert));
  UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GenerateCertTime",
                             base::TimeTicks::Now() - start,
                             base::TimeDelta::FromMilliseconds(1),
                             base::TimeDelta::FromMinutes(5),
                             50);
  *error = OK;
  return result.Pass();
}

}  // namespace

// Represents the output and result callback of a request.
class ChannelIDServiceRequest {
 public:
  ChannelIDServiceRequest(base::TimeTicks request_start,
                          const CompletionCallback& callback,
                          std::string* private_key,
                          std::string* cert)
      : request_start_(request_start),
        callback_(callback),
        private_key_(private_key),
        cert_(cert) {
  }

  // Ensures that the result callback will never be made.
  void Cancel() {
    RecordGetChannelIDResult(ASYNC_CANCELLED);
    callback_.Reset();
    private_key_ = NULL;
    cert_ = NULL;
  }

  // Copies the contents of |private_key| and |cert| to the caller's output
  // arguments and calls the callback.
  void Post(int error,
            const std::string& private_key,
            const std::string& cert) {
    switch (error) {
      case OK: {
        base::TimeDelta request_time = base::TimeTicks::Now() - request_start_;
        UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GetCertTimeAsync",
                                   request_time,
                                   base::TimeDelta::FromMilliseconds(1),
                                   base::TimeDelta::FromMinutes(5),
                                   50);
        RecordGetChannelIDTime(request_time);
        RecordGetChannelIDResult(ASYNC_SUCCESS);
        break;
      }
      case ERR_KEY_GENERATION_FAILED:
        RecordGetChannelIDResult(ASYNC_FAILURE_KEYGEN);
        break;
      case ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED:
        RecordGetChannelIDResult(ASYNC_FAILURE_CREATE_CERT);
        break;
      case ERR_PRIVATE_KEY_EXPORT_FAILED:
        RecordGetChannelIDResult(ASYNC_FAILURE_EXPORT_KEY);
        break;
      case ERR_INSUFFICIENT_RESOURCES:
        RecordGetChannelIDResult(WORKER_FAILURE);
        break;
      default:
        RecordGetChannelIDResult(ASYNC_FAILURE_UNKNOWN);
        break;
    }
    if (!callback_.is_null()) {
      *private_key_ = private_key;
      *cert_ = cert;
      callback_.Run(error);
    }
    delete this;
  }

  bool canceled() const { return callback_.is_null(); }

 private:
  base::TimeTicks request_start_;
  CompletionCallback callback_;
  std::string* private_key_;
  std::string* cert_;
};

// ChannelIDServiceWorker runs on a worker thread and takes care of the
// blocking process of performing key generation. Will take care of deleting
// itself once Start() is called.
class ChannelIDServiceWorker {
 public:
  typedef base::Callback<void(
      const std::string&,
      int,
      scoped_ptr<ChannelIDStore::ChannelID>)> WorkerDoneCallback;

  ChannelIDServiceWorker(
      const std::string& server_identifier,
      const WorkerDoneCallback& callback)
      : server_identifier_(server_identifier),
        serial_number_(base::RandInt(0, std::numeric_limits<int>::max())),
        origin_loop_(base::MessageLoopProxy::current()),
        callback_(callback) {
  }

  // Starts the worker on |task_runner|. If the worker fails to start, such as
  // if the task runner is shutting down, then it will take care of deleting
  // itself.
  bool Start(const scoped_refptr<base::TaskRunner>& task_runner) {
    DCHECK(origin_loop_->RunsTasksOnCurrentThread());

    return task_runner->PostTask(
        FROM_HERE,
        base::Bind(&ChannelIDServiceWorker::Run, base::Owned(this)));
  }

 private:
  void Run() {
    // Runs on a worker thread.
    int error = ERR_FAILED;
    scoped_ptr<ChannelIDStore::ChannelID> cert =
        GenerateChannelID(server_identifier_, serial_number_, &error);
    DVLOG(1) << "GenerateCert " << server_identifier_ << " returned " << error;
#if !defined(USE_OPENSSL)
    // Detach the thread from NSPR.
    // Calling NSS functions attaches the thread to NSPR, which stores
    // the NSPR thread ID in thread-specific data.
    // The threads in our thread pool terminate after we have called
    // PR_Cleanup. Unless we detach them from NSPR, net_unittests gets
    // segfaults on shutdown when the threads' thread-specific data
    // destructors run.
    PR_DetachThread();
#endif
    origin_loop_->PostTask(FROM_HERE,
                           base::Bind(callback_, server_identifier_, error,
                                      base::Passed(&cert)));
  }

  const std::string server_identifier_;
  // Note that serial_number_ must be initialized on a non-worker thread
  // (see documentation for GenerateCert).
  uint32 serial_number_;
  scoped_refptr<base::SequencedTaskRunner> origin_loop_;
  WorkerDoneCallback callback_;

  DISALLOW_COPY_AND_ASSIGN(ChannelIDServiceWorker);
};

// A ChannelIDServiceJob is a one-to-one counterpart of an
// ChannelIDServiceWorker. It lives only on the ChannelIDService's
// origin message loop.
class ChannelIDServiceJob {
 public:
  ChannelIDServiceJob(bool create_if_missing)
      : create_if_missing_(create_if_missing) {
  }

  ~ChannelIDServiceJob() {
    if (!requests_.empty())
      DeleteAllCanceled();
  }

  void AddRequest(ChannelIDServiceRequest* request,
                  bool create_if_missing = false) {
    create_if_missing_ |= create_if_missing;
    requests_.push_back(request);
  }

  void HandleResult(int error,
                    const std::string& private_key,
                    const std::string& cert) {
    PostAll(error, private_key, cert);
  }

  bool CreateIfMissing() const { return create_if_missing_; }

 private:
  void PostAll(int error,
               const std::string& private_key,
               const std::string& cert) {
    std::vector<ChannelIDServiceRequest*> requests;
    requests_.swap(requests);

    for (std::vector<ChannelIDServiceRequest*>::iterator
         i = requests.begin(); i != requests.end(); i++) {
      (*i)->Post(error, private_key, cert);
      // Post() causes the ChannelIDServiceRequest to delete itself.
    }
  }

  void DeleteAllCanceled() {
    for (std::vector<ChannelIDServiceRequest*>::iterator
         i = requests_.begin(); i != requests_.end(); i++) {
      if ((*i)->canceled()) {
        delete *i;
      } else {
        LOG(DFATAL) << "ChannelIDServiceRequest leaked!";
      }
    }
  }

  std::vector<ChannelIDServiceRequest*> requests_;
  bool create_if_missing_;
};

// static
const char ChannelIDService::kEPKIPassword[] = "";

ChannelIDService::RequestHandle::RequestHandle()
    : service_(NULL),
      request_(NULL) {}

ChannelIDService::RequestHandle::~RequestHandle() {
  Cancel();
}

void ChannelIDService::RequestHandle::Cancel() {
  if (request_) {
    service_->CancelRequest(request_);
    request_ = NULL;
    callback_.Reset();
  }
}

void ChannelIDService::RequestHandle::RequestStarted(
    ChannelIDService* service,
    ChannelIDServiceRequest* request,
    const CompletionCallback& callback) {
  DCHECK(request_ == NULL);
  service_ = service;
  request_ = request;
  callback_ = callback;
}

void ChannelIDService::RequestHandle::OnRequestComplete(int result) {
  request_ = NULL;
  // Running the callback might delete |this|, so we can't touch any of our
  // members afterwards. Reset callback_ first.
  base::ResetAndReturn(&callback_).Run(result);
}

ChannelIDService::ChannelIDService(
    ChannelIDStore* channel_id_store,
    const scoped_refptr<base::TaskRunner>& task_runner)
    : channel_id_store_(channel_id_store),
      task_runner_(task_runner),
      requests_(0),
      cert_store_hits_(0),
      inflight_joins_(0),
      workers_created_(0),
      weak_ptr_factory_(this) {
  base::Time start = base::Time::Now();
  base::Time end = start + base::TimeDelta::FromDays(
      kValidityPeriodInDays + kSystemTimeValidityBufferInDays);
  is_system_time_valid_ = x509_util::IsSupportedValidityRange(start, end);
}

ChannelIDService::~ChannelIDService() {
  STLDeleteValues(&inflight_);
}

//static
std::string ChannelIDService::GetDomainForHost(const std::string& host) {
  std::string domain =
      registry_controlled_domains::GetDomainAndRegistry(
          host, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  if (domain.empty())
    return host;
  return domain;
}

int ChannelIDService::GetOrCreateChannelID(
    const std::string& host,
    std::string* private_key,
    std::string* cert,
    const CompletionCallback& callback,
    RequestHandle* out_req) {
  DVLOG(1) << __FUNCTION__ << " " << host;
  DCHECK(CalledOnValidThread());
  base::TimeTicks request_start = base::TimeTicks::Now();

  if (callback.is_null() || !private_key || !cert || host.empty()) {
    RecordGetChannelIDResult(INVALID_ARGUMENT);
    return ERR_INVALID_ARGUMENT;
  }

  std::string domain = GetDomainForHost(host);
  if (domain.empty()) {
    RecordGetChannelIDResult(INVALID_ARGUMENT);
    return ERR_INVALID_ARGUMENT;
  }

  requests_++;

  // See if a request for the same domain is currently in flight.
  bool create_if_missing = true;
  if (JoinToInFlightRequest(request_start, domain, private_key, cert,
                            create_if_missing, callback, out_req)) {
    return ERR_IO_PENDING;
  }

  int err = LookupChannelID(request_start, domain, private_key, cert,
                                  create_if_missing, callback, out_req);
  if (err == ERR_FILE_NOT_FOUND) {
    // Sync lookup did not find a valid cert.  Start generating a new one.
    workers_created_++;
    ChannelIDServiceWorker* worker = new ChannelIDServiceWorker(
        domain,
        base::Bind(&ChannelIDService::GeneratedChannelID,
                   weak_ptr_factory_.GetWeakPtr()));
    if (!worker->Start(task_runner_)) {
      // TODO(rkn): Log to the NetLog.
      LOG(ERROR) << "ChannelIDServiceWorker couldn't be started.";
      RecordGetChannelIDResult(WORKER_FAILURE);
      return ERR_INSUFFICIENT_RESOURCES;
    }
    // We are waiting for cert generation.  Create a job & request to track it.
    ChannelIDServiceJob* job = new ChannelIDServiceJob(create_if_missing);
    inflight_[domain] = job;

    ChannelIDServiceRequest* request = new ChannelIDServiceRequest(
        request_start,
        base::Bind(&RequestHandle::OnRequestComplete,
                   base::Unretained(out_req)),
        private_key,
        cert);
    job->AddRequest(request);
    out_req->RequestStarted(this, request, callback);
    return ERR_IO_PENDING;
  }

  return err;
}

int ChannelIDService::GetChannelID(
    const std::string& host,
    std::string* private_key,
    std::string* cert,
    const CompletionCallback& callback,
    RequestHandle* out_req) {
  DVLOG(1) << __FUNCTION__ << " " << host;
  DCHECK(CalledOnValidThread());
  base::TimeTicks request_start = base::TimeTicks::Now();

  if (callback.is_null() || !private_key || !cert || host.empty()) {
    RecordGetChannelIDResult(INVALID_ARGUMENT);
    return ERR_INVALID_ARGUMENT;
  }

  std::string domain = GetDomainForHost(host);
  if (domain.empty()) {
    RecordGetChannelIDResult(INVALID_ARGUMENT);
    return ERR_INVALID_ARGUMENT;
  }

  requests_++;

  // See if a request for the same domain currently in flight.
  bool create_if_missing = false;
  if (JoinToInFlightRequest(request_start, domain, private_key, cert,
                            create_if_missing, callback, out_req)) {
    return ERR_IO_PENDING;
  }

  int err = LookupChannelID(request_start, domain, private_key, cert,
                            create_if_missing, callback, out_req);
  return err;
}

void ChannelIDService::GotChannelID(
    int err,
    const std::string& server_identifier,
    base::Time expiration_time,
    const std::string& key,
    const std::string& cert) {
  DCHECK(CalledOnValidThread());

  std::map<std::string, ChannelIDServiceJob*>::iterator j;
  j = inflight_.find(server_identifier);
  if (j == inflight_.end()) {
    NOTREACHED();
    return;
  }

  if (err == OK) {
    // Async DB lookup found a valid cert.
    DVLOG(1) << "Cert store had valid cert for " << server_identifier;
    cert_store_hits_++;
    // ChannelIDServiceRequest::Post will do the histograms and stuff.
    HandleResult(OK, server_identifier, key, cert);
    return;
  }
  // Async lookup failed or the certificate was missing. Return the error
  // directly, unless the certificate was missing and a request asked to create
  // one.
  if (err != ERR_FILE_NOT_FOUND || !j->second->CreateIfMissing()) {
    HandleResult(err, server_identifier, key, cert);
    return;
  }
  // At least one request asked to create a cert => start generating a new one.
  workers_created_++;
  ChannelIDServiceWorker* worker = new ChannelIDServiceWorker(
      server_identifier,
      base::Bind(&ChannelIDService::GeneratedChannelID,
                 weak_ptr_factory_.GetWeakPtr()));
  if (!worker->Start(task_runner_)) {
    // TODO(rkn): Log to the NetLog.
    LOG(ERROR) << "ChannelIDServiceWorker couldn't be started.";
    HandleResult(ERR_INSUFFICIENT_RESOURCES,
                 server_identifier,
                 std::string(),
                 std::string());
  }
}

ChannelIDStore* ChannelIDService::GetChannelIDStore() {
  return channel_id_store_.get();
}

void ChannelIDService::CancelRequest(ChannelIDServiceRequest* req) {
  DCHECK(CalledOnValidThread());
  req->Cancel();
}

void ChannelIDService::GeneratedChannelID(
    const std::string& server_identifier,
    int error,
    scoped_ptr<ChannelIDStore::ChannelID> cert) {
  DCHECK(CalledOnValidThread());

  if (error == OK) {
    // TODO(mattm): we should just Pass() the cert object to
    // SetChannelID().
    channel_id_store_->SetChannelID(
        cert->server_identifier(),
        cert->creation_time(),
        cert->expiration_time(),
        cert->private_key(),
        cert->cert());

    HandleResult(error, server_identifier, cert->private_key(), cert->cert());
  } else {
    HandleResult(error, server_identifier, std::string(), std::string());
  }
}

void ChannelIDService::HandleResult(
    int error,
    const std::string& server_identifier,
    const std::string& private_key,
    const std::string& cert) {
  DCHECK(CalledOnValidThread());

  std::map<std::string, ChannelIDServiceJob*>::iterator j;
  j = inflight_.find(server_identifier);
  if (j == inflight_.end()) {
    NOTREACHED();
    return;
  }
  ChannelIDServiceJob* job = j->second;
  inflight_.erase(j);

  job->HandleResult(error, private_key, cert);
  delete job;
}

bool ChannelIDService::JoinToInFlightRequest(
    const base::TimeTicks& request_start,
    const std::string& domain,
    std::string* private_key,
    std::string* cert,
    bool create_if_missing,
    const CompletionCallback& callback,
    RequestHandle* out_req) {
  ChannelIDServiceJob* job = NULL;
  std::map<std::string, ChannelIDServiceJob*>::const_iterator j =
      inflight_.find(domain);
  if (j != inflight_.end()) {
    // A request for the same domain is in flight already. We'll attach our
    // callback, but we'll also mark it as requiring a cert if one's mising.
    job = j->second;
    inflight_joins_++;

    ChannelIDServiceRequest* request = new ChannelIDServiceRequest(
        request_start,
        base::Bind(&RequestHandle::OnRequestComplete,
                   base::Unretained(out_req)),
        private_key,
        cert);
    job->AddRequest(request, create_if_missing);
    out_req->RequestStarted(this, request, callback);
    return true;
  }
  return false;
}

int ChannelIDService::LookupChannelID(
    const base::TimeTicks& request_start,
    const std::string& domain,
    std::string* private_key,
    std::string* cert,
    bool create_if_missing,
    const CompletionCallback& callback,
    RequestHandle* out_req) {
  // Check if a domain bound cert already exists for this domain. Note that
  // |expiration_time| is ignored, and expired certs are considered valid.
  base::Time expiration_time;
  int err = channel_id_store_->GetChannelID(
      domain,
      &expiration_time  /* ignored */,
      private_key,
      cert,
      base::Bind(&ChannelIDService::GotChannelID,
                 weak_ptr_factory_.GetWeakPtr()));

  if (err == OK) {
    // Sync lookup found a valid cert.
    DVLOG(1) << "Cert store had valid cert for " << domain;
    cert_store_hits_++;
    RecordGetChannelIDResult(SYNC_SUCCESS);
    base::TimeDelta request_time = base::TimeTicks::Now() - request_start;
    UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time);
    RecordGetChannelIDTime(request_time);
    return OK;
  }

  if (err == ERR_IO_PENDING) {
    // We are waiting for async DB lookup.  Create a job & request to track it.
    ChannelIDServiceJob* job = new ChannelIDServiceJob(create_if_missing);
    inflight_[domain] = job;

    ChannelIDServiceRequest* request = new ChannelIDServiceRequest(
        request_start,
        base::Bind(&RequestHandle::OnRequestComplete,
                   base::Unretained(out_req)),
        private_key,
        cert);
    job->AddRequest(request);
    out_req->RequestStarted(this, request, callback);
    return ERR_IO_PENDING;
  }

  return err;
}

int ChannelIDService::cert_count() {
  return channel_id_store_->GetChannelIDCount();
}

}  // namespace net
