// Copyright (c) 2012 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/base/cert_database.h"

#include <Security/Security.h>

#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/message_loop.h"
#include "base/observer_list_threadsafe.h"
#include "base/process_util.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "crypto/mac_security_services_lock.h"
#include "net/base/net_errors.h"
#include "net/base/x509_certificate.h"

namespace net {

// Helper that observes events from the Keychain and forwards them to the
// given CertDatabase.
class CertDatabase::Notifier {
 public:
  // Creates a new Notifier that will forward Keychain events to |cert_db|.
  // |message_loop| must refer to a thread with an associated CFRunLoop - a
  // TYPE_UI thread. Events will be dispatched from this message loop.
  Notifier(CertDatabase* cert_db, MessageLoop* message_loop)
      : cert_db_(cert_db),
        registered_(false),
        called_shutdown_(false) {
    // Ensure an associated CFRunLoop.
    DCHECK(message_loop->IsType(MessageLoop::TYPE_UI));
    task_runner_ = message_loop->message_loop_proxy();
    task_runner_->PostTask(FROM_HERE,
                           base::Bind(&Notifier::Init,
                                      base::Unretained(this)));
  }

  // Should be called from the |task_runner_|'s thread. Use Shutdown()
  // to shutdown on arbitrary threads.
  ~Notifier() {
    DCHECK(called_shutdown_);
    // Only unregister from the same thread where registration was performed.
    if (registered_ && task_runner_->RunsTasksOnCurrentThread())
      SecKeychainRemoveCallback(&Notifier::KeychainCallback);
  }

  void Shutdown() {
    called_shutdown_ = true;
    if (!task_runner_->DeleteSoon(FROM_HERE, this)) {
      // If the task runner is no longer running, it's safe to just delete
      // the object, since no further events will or can be delivered by
      // Keychain Services.
      delete this;
    }
  }

 private:
  void Init() {
    SecKeychainEventMask event_mask =
        kSecKeychainListChangedMask | kSecTrustSettingsChangedEventMask;
    OSStatus status = SecKeychainAddCallback(&Notifier::KeychainCallback,
                                             event_mask, this);
    if (status == noErr)
      registered_ = true;
  }

  // SecKeychainCallback function that receives notifications from securityd
  // and forwards them to the |cert_db_|.
  static OSStatus KeychainCallback(SecKeychainEvent keychain_event,
                                   SecKeychainCallbackInfo* info,
                                   void* context);

  CertDatabase* const cert_db_;
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  bool registered_;
  bool called_shutdown_;
};

// static
OSStatus CertDatabase::Notifier::KeychainCallback(
    SecKeychainEvent keychain_event,
    SecKeychainCallbackInfo* info,
    void* context) {
  Notifier* that = reinterpret_cast<Notifier*>(context);

  if (info->version > SEC_KEYCHAIN_SETTINGS_VERS1) {
    NOTREACHED();
    return errSecWrongSecVersion;
  }

  if (info->pid == base::GetCurrentProcId()) {
    // Ignore events generated by the current process, as the assumption is
    // that they have already been handled. This may miss events that
    // originated as a result of spawning native dialogs that allow the user
    // to modify Keychain settings. However, err on the side of missing
    // events rather than sending too many events.
    return errSecSuccess;
  }

  switch (keychain_event) {
    case kSecKeychainListChangedEvent:
    case kSecTrustSettingsChangedEvent:
      that->cert_db_->NotifyObserversOfCertTrustChanged(NULL);
      break;
  }

  return errSecSuccess;
}

void CertDatabase::SetMessageLoopForKeychainEvents() {
  // Shutdown will take care to delete the notifier on the right thread.
  if (notifier_.get())
    notifier_.release()->Shutdown();

  notifier_.reset(new Notifier(this, MessageLoopForUI::current()));
}

CertDatabase::CertDatabase()
    : observer_list_(new ObserverListThreadSafe<Observer>) {
}

CertDatabase::~CertDatabase() {
  // Shutdown will take care to delete the notifier on the right thread.
  if (notifier_.get())
    notifier_.release()->Shutdown();
}

int CertDatabase::CheckUserCert(X509Certificate* cert) {
  if (!cert)
    return ERR_CERT_INVALID;
  if (cert->HasExpired())
    return ERR_CERT_DATE_INVALID;

  // Verify the Keychain already has the corresponding private key:
  SecIdentityRef identity = NULL;
  OSStatus err = SecIdentityCreateWithCertificate(NULL, cert->os_cert_handle(),
                                                  &identity);
  if (err == errSecItemNotFound)
    return ERR_NO_PRIVATE_KEY_FOR_CERT;

  if (err != noErr || !identity) {
    // TODO(snej): Map the error code more intelligently.
    return ERR_CERT_INVALID;
  }

  CFRelease(identity);
  return OK;
}

int CertDatabase::AddUserCert(X509Certificate* cert) {
  OSStatus err;
  {
    base::AutoLock locked(crypto::GetMacSecurityServicesLock());
    err = SecCertificateAddToKeychain(cert->os_cert_handle(), NULL);
  }
  switch (err) {
    case noErr:
      CertDatabase::NotifyObserversOfCertAdded(cert);
      // Fall through.
    case errSecDuplicateItem:
      return OK;
    default:
      OSSTATUS_LOG(ERROR, err) << "CertDatabase failed to add cert to keychain";
      // TODO(snej): Map the error code more intelligently.
      return ERR_ADD_USER_CERT_FAILED;
  }
}

}  // namespace net
