//
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "shill/eap_credentials.h"

#include <string>
#include <utility>
#include <vector>

#if defined(__ANDROID__)
#include <dbus/service_constants.h>
#else
#include <chromeos/dbus/service_constants.h>
#endif  // __ANDROID__

#include "shill/certificate_file.h"
#include "shill/key_value_store.h"
#include "shill/logging.h"
#include "shill/metrics.h"
#include "shill/property_accessor.h"
#include "shill/property_store.h"
#include "shill/service.h"
#include "shill/store_interface.h"
#include "shill/supplicant/wpa_supplicant.h"

using base::FilePath;
using std::string;
using std::vector;

using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kService;
static string ObjectID(const EapCredentials* e) { return "(eap_credentials)"; }
}

const char EapCredentials::kStorageEapAnonymousIdentity[] =
    "EAP.AnonymousIdentity";
const char EapCredentials::kStorageEapCACert[] = "EAP.CACert";
const char EapCredentials::kStorageEapCACertID[] = "EAP.CACertID";
const char EapCredentials::kStorageEapCACertNSS[] = "EAP.CACertNSS";
const char EapCredentials::kStorageEapCACertPEM[] = "EAP.CACertPEM";
const char EapCredentials::kStorageEapCertID[] = "EAP.CertID";
const char EapCredentials::kStorageEapClientCert[] = "EAP.ClientCert";
const char EapCredentials::kStorageEapEap[] = "EAP.EAP";
const char EapCredentials::kStorageEapIdentity[] = "EAP.Identity";
const char EapCredentials::kStorageEapInnerEap[] = "EAP.InnerEAP";
const char EapCredentials::kStorageEapKeyID[] = "EAP.KeyID";
const char EapCredentials::kStorageEapKeyManagement[] = "EAP.KeyMgmt";
const char EapCredentials::kStorageEapPIN[] = "EAP.PIN";
const char EapCredentials::kStorageEapPassword[] = "EAP.Password";
const char EapCredentials::kStorageEapPrivateKey[] = "EAP.PrivateKey";
const char EapCredentials::kStorageEapPrivateKeyPassword[] =
    "EAP.PrivateKeyPassword";
const char EapCredentials::kStorageEapSubjectMatch[] =
    "EAP.SubjectMatch";
const char EapCredentials::kStorageEapUseProactiveKeyCaching[] =
    "EAP.UseProactiveKeyCaching";
const char EapCredentials::kStorageEapUseSystemCAs[] = "EAP.UseSystemCAs";

EapCredentials::EapCredentials() : use_system_cas_(true),
                                   use_proactive_key_caching_(false) {}

EapCredentials::~EapCredentials() {}

// static
void EapCredentials::PopulateSupplicantProperties(
    CertificateFile* certificate_file, KeyValueStore* params) const {
  string ca_cert = ca_cert_;
  if (!ca_cert_pem_.empty()) {
    FilePath certfile =
        certificate_file->CreatePEMFromStrings(ca_cert_pem_);
    if (certfile.empty()) {
      LOG(ERROR) << "Unable to extract PEM certificate.";
    } else {
      ca_cert = certfile.value();
    }
  }


  using KeyVal = std::pair<const char*, const char*>;
  KeyVal init_propertyvals[] = {
    // Authentication properties.
    KeyVal(WPASupplicant::kNetworkPropertyEapAnonymousIdentity,
           anonymous_identity_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapClientCert,
           client_cert_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapIdentity, identity_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapCaPassword,
           password_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKey,
           private_key_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapPrivateKeyPassword,
           private_key_password_.c_str()),

    // Non-authentication properties.
    KeyVal(WPASupplicant::kNetworkPropertyEapCaCert, ca_cert.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapCaCertId,
           ca_cert_id_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapEap, eap_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapInnerEap,
           inner_eap_.c_str()),
    KeyVal(WPASupplicant::kNetworkPropertyEapSubjectMatch,
           subject_match_.c_str())
  };

  vector<KeyVal> propertyvals(init_propertyvals,
                              init_propertyvals + arraysize(init_propertyvals));
  if (use_system_cas_) {
    propertyvals.push_back(KeyVal(
        WPASupplicant::kNetworkPropertyCaPath, WPASupplicant::kCaPath));
  } else if (ca_cert.empty()) {
    LOG(WARNING) << __func__
                 << ": No certificate authorities are configured."
                 << " Server certificates will be accepted"
                 << " unconditionally.";
  }

  if (ClientAuthenticationUsesCryptoToken()) {
    propertyvals.push_back(KeyVal(
        WPASupplicant::kNetworkPropertyEapCertId, cert_id_.c_str()));
    propertyvals.push_back(KeyVal(
        WPASupplicant::kNetworkPropertyEapKeyId, key_id_.c_str()));
  }

  if (ClientAuthenticationUsesCryptoToken() || !ca_cert_id_.empty()) {
    propertyvals.push_back(KeyVal(
        WPASupplicant::kNetworkPropertyEapPin, pin_.c_str()));
    propertyvals.push_back(KeyVal(
        WPASupplicant::kNetworkPropertyEngineId,
        WPASupplicant::kEnginePKCS11));
    // We can't use the propertyvals vector for this since this argument
    // is a uint32_t, not a string.
    params->SetUint(WPASupplicant::kNetworkPropertyEngine,
                   WPASupplicant::kDefaultEngine);
  }

  if (use_proactive_key_caching_) {
    params->SetUint(WPASupplicant::kNetworkPropertyEapProactiveKeyCaching,
                   WPASupplicant::kProactiveKeyCachingEnabled);
  } else {
    params->SetUint(WPASupplicant::kNetworkPropertyEapProactiveKeyCaching,
                   WPASupplicant::kProactiveKeyCachingDisabled);
  }

  for (const auto& keyval : propertyvals) {
    if (strlen(keyval.second) > 0) {
      params->SetString(keyval.first, keyval.second);
    }
  }
}

// static
void EapCredentials::PopulateWiMaxProperties(KeyValueStore* params) const {
  if (!anonymous_identity_.empty()) {
    params->SetString(wimax_manager::kEAPAnonymousIdentity,
                      anonymous_identity_);
  }
  if (!identity_.empty()) {
    params->SetString(wimax_manager::kEAPUserIdentity, identity_);
  }
  if (!password_.empty()) {
    params->SetString(wimax_manager::kEAPUserPassword, password_);
  }
}

void EapCredentials::InitPropertyStore(PropertyStore* store) {
  // Authentication properties.
  store->RegisterString(kEapAnonymousIdentityProperty, &anonymous_identity_);
  store->RegisterString(kEapCertIdProperty, &cert_id_);
  store->RegisterString(kEapClientCertProperty, &client_cert_);
  store->RegisterString(kEapIdentityProperty, &identity_);
  store->RegisterString(kEapKeyIdProperty, &key_id_);
  HelpRegisterDerivedString(store,
                            kEapKeyMgmtProperty,
                            &EapCredentials::GetKeyManagement,
                            &EapCredentials::SetKeyManagement);
  HelpRegisterWriteOnlyDerivedString(store,
                                     kEapPasswordProperty,
                                     &EapCredentials::SetEapPassword,
                                     nullptr,
                                     &password_);
  store->RegisterString(kEapPinProperty, &pin_);
  store->RegisterString(kEapPrivateKeyProperty, &private_key_);
  HelpRegisterWriteOnlyDerivedString(store,
                                     kEapPrivateKeyPasswordProperty,
                                     &EapCredentials::SetEapPrivateKeyPassword,
                                     nullptr,
                                     &private_key_password_);

  // Non-authentication properties.
  store->RegisterStrings(kEapCaCertPemProperty, &ca_cert_pem_);
  store->RegisterString(kEapCaCertIdProperty, &ca_cert_id_);
  store->RegisterString(kEapCaCertNssProperty, &ca_cert_nss_);
  store->RegisterString(kEapCaCertProperty, &ca_cert_);
  store->RegisterString(kEapMethodProperty, &eap_);
  store->RegisterString(kEapPhase2AuthProperty, &inner_eap_);
  store->RegisterString(kEapSubjectMatchProperty, &subject_match_);
  store->RegisterBool(kEapUseProactiveKeyCachingProperty,
                      &use_proactive_key_caching_);
  store->RegisterBool(kEapUseSystemCasProperty, &use_system_cas_);
}

// static
bool EapCredentials::IsEapAuthenticationProperty(const string property) {
  return
      property == kEapAnonymousIdentityProperty ||
      property == kEapCertIdProperty ||
      property == kEapClientCertProperty ||
      property == kEapIdentityProperty ||
      property == kEapKeyIdProperty ||
      property == kEapKeyMgmtProperty ||
      property == kEapPasswordProperty ||
      property == kEapPinProperty ||
      property == kEapPrivateKeyProperty ||
      property == kEapPrivateKeyPasswordProperty;
}

bool EapCredentials::IsConnectable() const {
  // Identity is required.
  if (identity_.empty()) {
    SLOG(this, 2) << "Not connectable: Identity is empty.";
    return false;
  }

  if (!client_cert_.empty() || !cert_id_.empty()) {
    // If a client certificate is being used, we must have a private key.
    if (private_key_.empty() && key_id_.empty()) {
      SLOG(this, 2)
          << "Not connectable: Client certificate but no private key.";
      return false;
    }
  }
  if (!cert_id_.empty() || !key_id_.empty() ||
      !ca_cert_id_.empty()) {
    // If PKCS#11 data is needed, a PIN is required.
    if (pin_.empty()) {
      SLOG(this, 2) << "Not connectable: PKCS#11 data but no PIN.";
      return false;
    }
  }

  // For EAP-TLS, a client certificate is required.
  if (eap_.empty() || eap_ == kEapMethodTLS) {
    if ((!client_cert_.empty() || !cert_id_.empty()) &&
        (!private_key_.empty() || !key_id_.empty())) {
      SLOG(this, 2) << "Connectable: EAP-TLS with a client cert and key.";
      return true;
    }
  }

  // For EAP types other than TLS (e.g. EAP-TTLS or EAP-PEAP, password is the
  // minimum requirement), at least an identity + password is required.
  if (eap_.empty() || eap_ != kEapMethodTLS) {
    if (!password_.empty()) {
      SLOG(this, 2) << "Connectable. !EAP-TLS and has a password.";
      return true;
    }
  }

  SLOG(this, 2) << "Not connectable: No suitable EAP configuration was found.";
  return false;
}

bool EapCredentials::IsConnectableUsingPassphrase() const {
  return !identity_.empty() && !password_.empty();
}

void EapCredentials::Load(StoreInterface* storage, const string& id) {
  // Authentication properties.
  storage->GetCryptedString(id,
                            kStorageEapAnonymousIdentity,
                            &anonymous_identity_);
  storage->GetString(id, kStorageEapCertID, &cert_id_);
  storage->GetString(id, kStorageEapClientCert, &client_cert_);
  storage->GetCryptedString(id, kStorageEapIdentity, &identity_);
  storage->GetString(id, kStorageEapKeyID, &key_id_);
  string key_management;
  storage->GetString(id, kStorageEapKeyManagement, &key_management);
  SetKeyManagement(key_management, nullptr);
  storage->GetCryptedString(id, kStorageEapPassword, &password_);
  storage->GetString(id, kStorageEapPIN, &pin_);
  storage->GetString(id, kStorageEapPrivateKey, &private_key_);
  storage->GetCryptedString(id,
                            kStorageEapPrivateKeyPassword,
                            &private_key_password_);

  // Non-authentication properties.
  storage->GetString(id, kStorageEapCACert, &ca_cert_);
  storage->GetString(id, kStorageEapCACertID, &ca_cert_id_);
  storage->GetString(id, kStorageEapCACertNSS, &ca_cert_nss_);
  storage->GetStringList(id, kStorageEapCACertPEM, &ca_cert_pem_);
  storage->GetString(id, kStorageEapEap, &eap_);
  storage->GetString(id, kStorageEapInnerEap, &inner_eap_);
  storage->GetString(id, kStorageEapSubjectMatch, &subject_match_);
  storage->GetBool(id, kStorageEapUseProactiveKeyCaching,
                   &use_proactive_key_caching_);
  storage->GetBool(id, kStorageEapUseSystemCAs, &use_system_cas_);
}

void EapCredentials::OutputConnectionMetrics(
    Metrics* metrics, Technology::Identifier technology) const {
  Metrics::EapOuterProtocol outer_protocol =
      Metrics::EapOuterProtocolStringToEnum(eap_);
  metrics->SendEnumToUMA(
      metrics->GetFullMetricName(Metrics::kMetricNetworkEapOuterProtocolSuffix,
                                 technology),
      outer_protocol,
      Metrics::kMetricNetworkEapOuterProtocolMax);

  Metrics::EapInnerProtocol inner_protocol =
      Metrics::EapInnerProtocolStringToEnum(inner_eap_);
  metrics->SendEnumToUMA(
      metrics->GetFullMetricName(Metrics::kMetricNetworkEapInnerProtocolSuffix,
                                 technology),
      inner_protocol,
      Metrics::kMetricNetworkEapInnerProtocolMax);
}

void EapCredentials::Save(StoreInterface* storage, const string& id,
                          bool save_credentials) const {
  // Authentication properties.
  Service::SaveString(storage,
                      id,
                      kStorageEapAnonymousIdentity,
                      anonymous_identity_,
                      true,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapCertID,
                      cert_id_,
                      false,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapClientCert,
                      client_cert_,
                      false,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapIdentity,
                      identity_,
                      true,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapKeyID,
                      key_id_,
                      false,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapKeyManagement,
                      key_management_,
                      false,
                      true);
  Service::SaveString(storage,
                      id,
                      kStorageEapPassword,
                      password_,
                      true,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapPIN,
                      pin_,
                      false,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapPrivateKey,
                      private_key_,
                      false,
                      save_credentials);
  Service::SaveString(storage,
                      id,
                      kStorageEapPrivateKeyPassword,
                      private_key_password_,
                      true,
                      save_credentials);

  // Non-authentication properties.
  Service::SaveString(storage, id, kStorageEapCACert, ca_cert_, false, true);
  Service::SaveString(storage,
                      id,
                      kStorageEapCACertID,
                      ca_cert_id_,
                      false,
                      true);
  Service::SaveString(storage,
                      id,
                      kStorageEapCACertNSS,
                      ca_cert_nss_,
                      false,
                      true);
  if (ca_cert_pem_.empty()) {
      storage->DeleteKey(id, kStorageEapCACertPEM);
  } else {
      storage->SetStringList(id, kStorageEapCACertPEM, ca_cert_pem_);
  }
  Service::SaveString(storage, id, kStorageEapEap, eap_, false, true);
  Service::SaveString(storage,
                      id,
                      kStorageEapInnerEap,
                      inner_eap_,
                      false,
                      true);
  Service::SaveString(storage,
                      id,
                      kStorageEapSubjectMatch,
                      subject_match_,
                      false,
                      true);
  storage->SetBool(id, kStorageEapUseProactiveKeyCaching,
                   use_proactive_key_caching_);
  storage->SetBool(id, kStorageEapUseSystemCAs, use_system_cas_);
}

void EapCredentials::Reset() {
  // Authentication properties.
  anonymous_identity_ = "";
  cert_id_ = "";
  client_cert_ = "";
  identity_ = "";
  key_id_ = "";
  // Do not reset key_management_, since it should never be emptied.
  password_ = "";
  pin_ = "";
  private_key_ = "";
  private_key_password_ = "";

  // Non-authentication properties.
  ca_cert_ = "";
  ca_cert_id_ = "";
  ca_cert_nss_ = "";
  ca_cert_pem_.clear();
  eap_ = "";
  inner_eap_ = "";
  subject_match_ = "";
  use_system_cas_ = true;
  use_proactive_key_caching_ = false;
}

bool EapCredentials::SetEapPassword(const string& password, Error* /*error*/) {
  if (password_ == password) {
    return false;
  }
  password_ = password;
  return true;
}

bool EapCredentials::SetEapPrivateKeyPassword(const string& password,
                                              Error* /*error*/) {
  if (private_key_password_ == password) {
    return false;
  }
  private_key_password_ = password;
  return true;
}

string EapCredentials::GetKeyManagement(Error* /*error*/) {
  return key_management_;
}

bool EapCredentials::SetKeyManagement(const std::string& key_management,
                                      Error* /*error*/) {
  if (key_management.empty()) {
    return false;
  }
  if (key_management_ == key_management) {
    return false;
  }
  key_management_ = key_management;
  return true;
}

bool EapCredentials::ClientAuthenticationUsesCryptoToken() const {
  return (eap_.empty() || eap_ == kEapMethodTLS ||
          inner_eap_ == kEapMethodTLS) &&
         (!cert_id_.empty() || !key_id_.empty());
}

void EapCredentials::HelpRegisterDerivedString(
    PropertyStore* store,
    const string& name,
    string(EapCredentials::*get)(Error* error),
    bool(EapCredentials::*set)(const string&, Error*)) {
  store->RegisterDerivedString(
      name,
      StringAccessor(new CustomAccessor<EapCredentials, string>(
          this, get, set)));
}

void EapCredentials::HelpRegisterWriteOnlyDerivedString(
    PropertyStore* store,
    const string& name,
    bool(EapCredentials::*set)(const string&, Error*),
    void(EapCredentials::*clear)(Error* error),
    const string* default_value) {
  store->RegisterDerivedString(
      name,
      StringAccessor(
          new CustomWriteOnlyAccessor<EapCredentials, string>(
              this, set, clear, default_value)));
}

}  // namespace shill
