// Copyright (c) 2012 The Chromium OS 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 "update_engine/certificate_checker.h"

#include <string>

#include <base/string_number_conversions.h>
#include <base/string_util.h>
#include <base/stringprintf.h>
#include <base/logging.h>
#include <curl/curl.h>
#include <metrics/metrics_library.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>

#include "update_engine/prefs_interface.h"
#include "update_engine/utils.h"

using std::string;

namespace chromeos_update_engine {

namespace {
// This should be in the same order of CertificateChecker::ServerToCheck, with
// the exception of kNone.
static const char* kReportToSendKey[2] =
    {kPrefsCertificateReportToSendUpdate,
     kPrefsCertificateReportToSendDownload};
}  // namespace {}

bool OpenSSLWrapper::GetCertificateDigest(X509_STORE_CTX* x509_ctx,
                                          int* out_depth,
                                          unsigned int* out_digest_length,
                                          unsigned char* out_digest) const {
  TEST_AND_RETURN_FALSE(out_digest);
  X509* certificate = X509_STORE_CTX_get_current_cert(x509_ctx);
  TEST_AND_RETURN_FALSE(certificate);
  int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
  if (out_depth)
    *out_depth = depth;

  unsigned int len;
  const EVP_MD* digest_function = EVP_sha256();
  bool success = X509_digest(certificate, digest_function, out_digest, &len);

  if (success && out_digest_length)
    *out_digest_length = len;
  return success;
}

// static
MetricsLibraryInterface* CertificateChecker::metrics_lib_ = NULL;

// static
PrefsInterface* CertificateChecker::prefs_ = NULL;

// static
OpenSSLWrapper* CertificateChecker::openssl_wrapper_ = NULL;

// static
CURLcode CertificateChecker::ProcessSSLContext(CURL* curl_handle,
                                               SSL_CTX* ssl_ctx,
                                               void* ptr) {
  // From here we set the SSL_CTX to another callback, from the openssl library,
  // which will be called after each server certificate is validated. However,
  // since openssl does not allow us to pass our own data pointer to the
  // callback, the certificate check will have to be done statically. Since we
  // need to know which update server we are using in order to check the
  // certificate, we hardcode Chrome OS's two known update servers here, and
  // define a different static callback for each. Since this code should only
  // run in official builds, this should not be a problem. However, if an update
  // server different from the ones listed here is used, the check will not
  // take place.
  ServerToCheck* server_to_check = reinterpret_cast<ServerToCheck*>(ptr);

  // We check which server to check and set the appropriate static callback.
  if (*server_to_check == kUpdate)
    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, VerifySSLCallbackUpdateCheck);
  if (*server_to_check == kDownload)
    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, VerifySSLCallbackDownload);

  return CURLE_OK;
}

// static
int CertificateChecker::VerifySSLCallbackUpdateCheck(int preverify_ok,
                                                     X509_STORE_CTX* x509_ctx) {
  return CertificateChecker::CheckCertificateChange(
      kUpdate, preverify_ok, x509_ctx) ? 1 : 0;
}

// static
int CertificateChecker::VerifySSLCallbackDownload(int preverify_ok,
                                                  X509_STORE_CTX* x509_ctx) {
  return CertificateChecker::CheckCertificateChange(
      kDownload, preverify_ok, x509_ctx) ? 1 : 0;
}

// static
bool CertificateChecker::CheckCertificateChange(
    ServerToCheck server_to_check, int preverify_ok,
    X509_STORE_CTX* x509_ctx) {
  static const char kUMAActionCertChanged[] =
      "Updater.ServerCertificateChanged";
  static const char kUMAActionCertFailed[] = "Updater.ServerCertificateFailed";
  TEST_AND_RETURN_FALSE(server_to_check != kNone);

  // If pre-verification failed, we are not interested in the current
  // certificate. We store a report to UMA and just propagate the fail result.
  if (!preverify_ok) {
    LOG_IF(WARNING, !prefs_->SetString(kReportToSendKey[server_to_check],
                                       kUMAActionCertFailed))
        << "Failed to store UMA report on a failure to validate "
        << "certificate from update server.";
    return false;
  }

  int depth;
  unsigned int digest_length;
  unsigned char digest[EVP_MAX_MD_SIZE];

  if (!openssl_wrapper_->GetCertificateDigest(x509_ctx,
                                              &depth,
                                              &digest_length,
                                              digest)) {
    LOG(WARNING) << "Failed to generate digest of X509 certificate "
                 << "from update server.";
    return true;
  }

  // We convert the raw bytes of the digest to an hex string, for storage in
  // prefs.
  string digest_string = base::HexEncode(digest, digest_length);

  string storage_key = StringPrintf("%s-%d-%d",
                                    kPrefsUpdateServerCertificate,
                                    server_to_check,
                                    depth);
  string stored_digest;
  // If there's no stored certificate, we just store the current one and return.
  if (!prefs_->GetString(storage_key, &stored_digest)) {
    LOG_IF(WARNING, !prefs_->SetString(storage_key, digest_string))
        << "Failed to store server certificate on storage key " << storage_key;
    return true;
  }

  // Certificate changed, we store a report to UMA and store the most recent
  // certificate.
  if (stored_digest != digest_string) {
    LOG_IF(WARNING, !prefs_->SetString(kReportToSendKey[server_to_check],
                                       kUMAActionCertChanged))
        << "Failed to store UMA report on a change on the "
        << "certificate from update server.";
    LOG_IF(WARNING, !prefs_->SetString(storage_key, digest_string))
        << "Failed to store server certificate on storage key " << storage_key;
  }

  // Since we don't perform actual SSL verification, we return success.
  return true;
}

// static
void CertificateChecker::FlushReport() {
  // This check shouldn't be needed, but it is useful for testing.
  TEST_AND_RETURN(metrics_lib_ && prefs_);

  // We flush reports for both servers.
  for (size_t i = 0; i < arraysize(kReportToSendKey); i++) {
    string report_to_send;
    if (prefs_->GetString(kReportToSendKey[i], &report_to_send) &&
        !report_to_send.empty()) {
      // There is a report to be sent. We send it and erase it.
      LOG_IF(WARNING, !metrics_lib_->SendUserActionToUMA(report_to_send))
          << "Failed to send server certificate report to UMA: "
          << report_to_send;
      // Since prefs doesn't provide deletion, we just set it as an empty
      // string.
      LOG_IF(WARNING, !prefs_->SetString(kReportToSendKey[i], ""))
          << "Failed to erase server certificate report to be sent to UMA";
    }
  }
}

}  // namespace chromeos_update_engine
