// Copyright 2013 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 "chromeos/network/policy_util.h"

#include <utility>

#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chromeos/network/network_profile.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_merger.h"
#include "chromeos/network/onc/onc_normalizer.h"
#include "chromeos/network/onc/onc_signature.h"
#include "chromeos/network/onc/onc_translator.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/network/shill_property_util.h"
#include "components/onc/onc_constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace policy_util {

namespace {

// This fake credential contains a random postfix which is extremely unlikely to
// be used by any user.
const char kFakeCredential[] = "FAKE_CREDENTIAL_VPaJDV9x";


// Removes all kFakeCredential values from sensitive fields (determined by
// onc::FieldIsCredential) of |onc_object|.
void RemoveFakeCredentials(
    const onc::OncValueSignature& signature,
    base::DictionaryValue* onc_object) {
  std::vector<std::string> entries_to_remove;
  for (base::DictionaryValue::Iterator it(*onc_object); !it.IsAtEnd();
       it.Advance()) {
    base::Value* value = nullptr;
    std::string field_name = it.key();
    // We need the non-const entry to remove nested values but DictionaryValue
    // has no non-const iterator.
    onc_object->GetWithoutPathExpansion(field_name, &value);

    // If |value| is a dictionary, recurse.
    base::DictionaryValue* nested_object = nullptr;
    if (value->GetAsDictionary(&nested_object)) {
      const onc::OncFieldSignature* field_signature =
          onc::GetFieldSignature(signature, field_name);
      if (field_signature)
        RemoveFakeCredentials(*field_signature->value_signature, nested_object);
      else
        LOG(ERROR) << "ONC has unrecognized field: " << field_name;
      continue;
    }

    // If |value| is a string, check if it is a fake credential.
    std::string string_value;
    if (value->GetAsString(&string_value) &&
        onc::FieldIsCredential(signature, field_name)) {
      if (string_value == kFakeCredential) {
        // The value wasn't modified by the UI, thus we remove the field to keep
        // the existing value that is stored in Shill.
        entries_to_remove.push_back(field_name);
      }
      // Otherwise, the value is set and modified by the UI, thus we keep that
      // value to overwrite whatever is stored in Shill.
    }
  }
  for (auto field_name : entries_to_remove)
    onc_object->RemoveWithoutPathExpansion(field_name, nullptr);
}

// Returns true if |policy| matches |actual_network|, which must be part of a
// ONC NetworkConfiguration. This should be the only such matching function
// within Chrome. Shill does such matching in several functions for network
// identification. For compatibility, we currently should stick to Shill's
// matching behavior.
bool IsPolicyMatching(const base::DictionaryValue& policy,
                      const base::DictionaryValue& actual_network) {
  std::string policy_type;
  policy.GetStringWithoutPathExpansion(::onc::network_config::kType,
                                       &policy_type);
  std::string actual_network_type;
  actual_network.GetStringWithoutPathExpansion(::onc::network_config::kType,
                                               &actual_network_type);
  if (policy_type != actual_network_type)
    return false;

  if (actual_network_type == ::onc::network_type::kEthernet) {
    const base::DictionaryValue* policy_ethernet = NULL;
    policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kEthernet,
                                             &policy_ethernet);
    const base::DictionaryValue* actual_ethernet = NULL;
    actual_network.GetDictionaryWithoutPathExpansion(
        ::onc::network_config::kEthernet, &actual_ethernet);
    if (!policy_ethernet || !actual_ethernet)
      return false;

    std::string policy_auth;
    policy_ethernet->GetStringWithoutPathExpansion(
        ::onc::ethernet::kAuthentication, &policy_auth);
    std::string actual_auth;
    actual_ethernet->GetStringWithoutPathExpansion(
        ::onc::ethernet::kAuthentication, &actual_auth);
    return policy_auth == actual_auth;
  } else if (actual_network_type == ::onc::network_type::kWiFi) {
    const base::DictionaryValue* policy_wifi = NULL;
    policy.GetDictionaryWithoutPathExpansion(::onc::network_config::kWiFi,
                                             &policy_wifi);
    const base::DictionaryValue* actual_wifi = NULL;
    actual_network.GetDictionaryWithoutPathExpansion(
        ::onc::network_config::kWiFi,
        &actual_wifi);
    if (!policy_wifi || !actual_wifi)
      return false;

    std::string policy_ssid;
    policy_wifi->GetStringWithoutPathExpansion(::onc::wifi::kHexSSID,
                                               &policy_ssid);
    std::string actual_ssid;
    actual_wifi->GetStringWithoutPathExpansion(::onc::wifi::kHexSSID,
                                               &actual_ssid);
    return (policy_ssid == actual_ssid);
  }
  return false;
}

// Returns true if AutoConnect is enabled by |policy| (as mandatory or
// recommended setting). Otherwise and on error returns false.
bool IsAutoConnectEnabledInPolicy(const base::DictionaryValue& policy) {
  std::string type;
  policy.GetStringWithoutPathExpansion(::onc::network_config::kType, &type);

  std::string autoconnect_key;
  std::string network_dict_key;
  if (type == ::onc::network_type::kWiFi) {
    network_dict_key = ::onc::network_config::kWiFi;
    autoconnect_key = ::onc::wifi::kAutoConnect;
  } else if (type == ::onc::network_type::kVPN) {
    network_dict_key = ::onc::network_config::kVPN;
    autoconnect_key = ::onc::vpn::kAutoConnect;
  } else {
    VLOG(2) << "Network type without autoconnect property.";
    return false;
  }

  const base::DictionaryValue* network_dict = NULL;
  policy.GetDictionaryWithoutPathExpansion(network_dict_key, &network_dict);
  if (!network_dict) {
    LOG(ERROR) << "ONC doesn't contain a " << network_dict_key
               << " dictionary.";
    return false;
  }

  bool autoconnect = false;
  network_dict->GetBooleanWithoutPathExpansion(autoconnect_key, &autoconnect);
  return autoconnect;
}

base::DictionaryValue* GetOrCreateDictionary(const std::string& key,
                                             base::DictionaryValue* dict) {
  base::DictionaryValue* inner_dict = NULL;
  if (!dict->GetDictionaryWithoutPathExpansion(key, &inner_dict)) {
    inner_dict = dict->SetDictionaryWithoutPathExpansion(
        key, base::MakeUnique<base::DictionaryValue>());
  }
  return inner_dict;
}

base::DictionaryValue* GetOrCreateNestedDictionary(
    const std::string& key1,
    const std::string& key2,
    base::DictionaryValue* dict) {
  base::DictionaryValue* inner_dict = GetOrCreateDictionary(key1, dict);
  return GetOrCreateDictionary(key2, inner_dict);
}

void ApplyGlobalAutoconnectPolicy(
    NetworkProfile::Type profile_type,
    base::DictionaryValue* augmented_onc_network) {
  std::string type;
  augmented_onc_network->GetStringWithoutPathExpansion(
      ::onc::network_config::kType, &type);
  if (type.empty()) {
    LOG(ERROR) << "ONC dictionary with no Type.";
    return;
  }

  // Managed dictionaries don't contain empty dictionaries (see onc_merger.cc),
  // so add the Autoconnect dictionary in case Shill didn't report a value.
  base::DictionaryValue* auto_connect_dictionary = NULL;
  if (type == ::onc::network_type::kWiFi) {
    auto_connect_dictionary =
        GetOrCreateNestedDictionary(::onc::network_config::kWiFi,
                                    ::onc::wifi::kAutoConnect,
                                    augmented_onc_network);
  } else if (type == ::onc::network_type::kVPN) {
    auto_connect_dictionary =
        GetOrCreateNestedDictionary(::onc::network_config::kVPN,
                                    ::onc::vpn::kAutoConnect,
                                    augmented_onc_network);
  } else {
    return;  // Network type without auto-connect property.
  }

  std::string policy_source;
  if (profile_type == NetworkProfile::TYPE_USER)
    policy_source = ::onc::kAugmentationUserPolicy;
  else if (profile_type == NetworkProfile::TYPE_SHARED)
    policy_source = ::onc::kAugmentationDevicePolicy;
  else
    NOTREACHED();

  auto_connect_dictionary->SetKey(policy_source, base::Value(false));
  auto_connect_dictionary->SetKey(::onc::kAugmentationEffectiveSetting,
                                  base::Value(policy_source));
}

}  // namespace

std::unique_ptr<base::DictionaryValue> CreateManagedONC(
    const base::DictionaryValue* global_policy,
    const base::DictionaryValue* network_policy,
    const base::DictionaryValue* user_settings,
    const base::DictionaryValue* active_settings,
    const NetworkProfile* profile) {
  const base::DictionaryValue* user_policy = NULL;
  const base::DictionaryValue* device_policy = NULL;
  const base::DictionaryValue* nonshared_user_settings = NULL;
  const base::DictionaryValue* shared_user_settings = NULL;

  if (profile) {
    if (profile->type() == NetworkProfile::TYPE_SHARED) {
      device_policy = network_policy;
      shared_user_settings = user_settings;
    } else if (profile->type() == NetworkProfile::TYPE_USER) {
      user_policy = network_policy;
      nonshared_user_settings = user_settings;
    } else {
      NOTREACHED();
    }
  }

  // This call also removes credentials from policies.
  std::unique_ptr<base::DictionaryValue> augmented_onc_network =
      onc::MergeSettingsAndPoliciesToAugmented(
          onc::kNetworkConfigurationSignature, user_policy, device_policy,
          nonshared_user_settings, shared_user_settings, active_settings);

  // If present, apply the Autoconnect policy only to networks that are not
  // managed by policy.
  if (!network_policy && global_policy && profile) {
    bool allow_only_policy_autoconnect = false;
    global_policy->GetBooleanWithoutPathExpansion(
        ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
        &allow_only_policy_autoconnect);
    if (allow_only_policy_autoconnect) {
      ApplyGlobalAutoconnectPolicy(profile->type(),
                                   augmented_onc_network.get());
    }
  }

  return augmented_onc_network;
}

void SetShillPropertiesForGlobalPolicy(
    const base::DictionaryValue& shill_dictionary,
    const base::DictionaryValue& global_network_policy,
    base::DictionaryValue* shill_properties_to_update) {
  // kAllowOnlyPolicyNetworksToAutoconnect is currently the only global config.

  std::string type;
  shill_dictionary.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
  if (NetworkTypePattern::Ethernet().MatchesType(type))
    return;  // Autoconnect for Ethernet cannot be configured.

  // By default all networks are allowed to autoconnect.
  bool only_policy_autoconnect = false;
  global_network_policy.GetBooleanWithoutPathExpansion(
      ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
      &only_policy_autoconnect);
  if (!only_policy_autoconnect)
    return;

  bool old_autoconnect = false;
  if (shill_dictionary.GetBooleanWithoutPathExpansion(
          shill::kAutoConnectProperty, &old_autoconnect) &&
      !old_autoconnect) {
    // Autoconnect is already explicitly disabled. No need to set it again.
    return;
  }

  // If autoconnect is not explicitly set yet, it might automatically be enabled
  // by Shill. To prevent that, disable it explicitly.
  shill_properties_to_update->SetKey(shill::kAutoConnectProperty,
                                     base::Value(false));
}

std::unique_ptr<base::DictionaryValue> CreateShillConfiguration(
    const NetworkProfile& profile,
    const std::string& guid,
    const base::DictionaryValue* global_policy,
    const base::DictionaryValue* network_policy,
    const base::DictionaryValue* user_settings) {
  std::unique_ptr<base::DictionaryValue> effective;
  ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
  if (network_policy) {
    if (profile.type() == NetworkProfile::TYPE_SHARED) {
      effective = onc::MergeSettingsAndPoliciesToEffective(
          NULL,  // no user policy
          network_policy,  // device policy
          NULL,  // no user settings
          user_settings);  // shared settings
      onc_source = ::onc::ONC_SOURCE_DEVICE_POLICY;
    } else if (profile.type() == NetworkProfile::TYPE_USER) {
      effective = onc::MergeSettingsAndPoliciesToEffective(
          network_policy,  // user policy
          NULL,  // no device policy
          user_settings,  // user settings
          NULL);  // no shared settings
      onc_source = ::onc::ONC_SOURCE_USER_POLICY;
    } else {
      NOTREACHED();
    }
  } else if (user_settings) {
    effective.reset(user_settings->DeepCopy());
    // TODO(pneubeck): change to source ONC_SOURCE_USER
    onc_source = ::onc::ONC_SOURCE_NONE;
  } else {
    NOTREACHED();
    onc_source = ::onc::ONC_SOURCE_NONE;
  }

  RemoveFakeCredentials(onc::kNetworkConfigurationSignature,
                        effective.get());

  effective->SetKey(::onc::network_config::kGUID, base::Value(guid));

  // Remove irrelevant fields.
  onc::Normalizer normalizer(true /* remove recommended fields */);
  effective = normalizer.NormalizeObject(&onc::kNetworkConfigurationSignature,
                                         *effective);

  std::unique_ptr<base::DictionaryValue> shill_dictionary(
      onc::TranslateONCObjectToShill(&onc::kNetworkConfigurationSignature,
                                     *effective));

  shill_dictionary->SetKey(shill::kProfileProperty, base::Value(profile.path));

  // If AutoConnect is enabled by policy, set the ManagedCredentials property to
  // indicate to Shill that this network can be used for autoconnect even
  // without a manual and successful connection attempt.
  // Note that this is only an indicator for the administrator's true intention,
  // i.e. when the administrator enables AutoConnect, we assume that the network
  // is indeed connectable.
  // Ideally, we would know whether the (policy) provided credentials are
  // complete and only set ManagedCredentials in that case.
  if (network_policy && IsAutoConnectEnabledInPolicy(*network_policy)) {
    VLOG(1) << "Enable ManagedCredentials for managed network with GUID "
            << guid;
    shill_dictionary->SetKey(shill::kManagedCredentialsProperty,
                             base::Value(true));
  }

  if (!network_policy && global_policy) {
    // The network isn't managed. Global network policies have to be applied.
    SetShillPropertiesForGlobalPolicy(
        *shill_dictionary, *global_policy, shill_dictionary.get());
  }

  std::unique_ptr<NetworkUIData> ui_data(
      NetworkUIData::CreateFromONC(onc_source));

  if (user_settings) {
    // Shill doesn't know that sensitive data is contained in the UIData
    // property and might write it into logs or other insecure places. Thus, we
    // have to remove or mask credentials.
    //
    // Shill's GetProperties doesn't return credentials. Masking credentials
    // instead of just removing them, allows remembering if a credential is set
    // or not.
    std::unique_ptr<base::DictionaryValue> sanitized_user_settings(
        onc::MaskCredentialsInOncObject(onc::kNetworkConfigurationSignature,
                                        *user_settings, kFakeCredential));
    ui_data->set_user_settings(std::move(sanitized_user_settings));
  }

  shill_property_util::SetUIData(*ui_data, shill_dictionary.get());

  VLOG(2) << "Created Shill properties: " << *shill_dictionary;

  return shill_dictionary;
}

const base::DictionaryValue* FindMatchingPolicy(
    const GuidToPolicyMap& policies,
    const base::DictionaryValue& actual_network) {
  for (auto it = policies.begin(); it != policies.end(); ++it) {
    if (IsPolicyMatching(*it->second, actual_network))
      return it->second.get();
  }
  return NULL;
}

}  // namespace policy_util

}  // namespace chromeos
