| Index: chrome/browser/chromeos/platform_keys/key_permissions.cc
|
| diff --git a/chrome/browser/chromeos/platform_keys/key_permissions.cc b/chrome/browser/chromeos/platform_keys/key_permissions.cc
|
| index eb936b136e864acf58cf4766d02139b79e7d083e..ddc9fa9a2133a33e1ede83b19fa6c135184b57cc 100644
|
| --- a/chrome/browser/chromeos/platform_keys/key_permissions.cc
|
| +++ b/chrome/browser/chromeos/platform_keys/key_permissions.cc
|
| @@ -8,8 +8,16 @@
|
| #include "base/bind.h"
|
| #include "base/callback.h"
|
| #include "base/logging.h"
|
| +#include "base/prefs/pref_service.h"
|
| +#include "base/prefs/scoped_user_pref_update.h"
|
| #include "base/values.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "components/policy/core/common/policy_map.h"
|
| +#include "components/policy/core/common/policy_namespace.h"
|
| +#include "components/policy/core/common/policy_service.h"
|
| +#include "components/pref_registry/pref_registry_syncable.h"
|
| #include "extensions/browser/state_store.h"
|
| +#include "policy/policy_constants.h"
|
|
|
| namespace chromeos {
|
|
|
| @@ -35,6 +43,9 @@ const char kStateStoreSPKI[] = "SPKI";
|
| const char kStateStoreSignOnce[] = "signOnce";
|
| const char kStateStoreSignUnlimited[] = "signUnlimited";
|
|
|
| +const char kPrefIsCorporateKey[] = "is_platform_key";
|
| +const char kPolicyAllowCorporateKeyUsage[] = "allowCorporateKeyUsage";
|
| +
|
| } // namespace
|
|
|
| struct KeyPermissions::PermissionsForExtension::KeyEntry {
|
| @@ -51,9 +62,8 @@ struct KeyPermissions::PermissionsForExtension::KeyEntry {
|
| bool sign_once = false;
|
|
|
| // True if the key can be used for signing an unlimited number of times.
|
| - // This permission is granted by the user or by policy to allow the extension
|
| - // to use the key for signing through the enterprise.platformKeys or
|
| - // platformKeys API.
|
| + // This permission is granted by the user to allow the extension to use the
|
| + // key for signing through the enterprise.platformKeys or platformKeys API.
|
| // This permission is granted until revoked by the user or the policy.
|
| bool sign_unlimited = false;
|
| };
|
| @@ -61,8 +71,15 @@ struct KeyPermissions::PermissionsForExtension::KeyEntry {
|
| KeyPermissions::PermissionsForExtension::PermissionsForExtension(
|
| const std::string& extension_id,
|
| scoped_ptr<base::Value> state_store_value,
|
| + PrefService* profile_prefs,
|
| + policy::PolicyService* profile_policies,
|
| KeyPermissions* key_permissions)
|
| - : extension_id_(extension_id), key_permissions_(key_permissions) {
|
| + : extension_id_(extension_id),
|
| + profile_prefs_(profile_prefs),
|
| + profile_policies_(profile_policies),
|
| + key_permissions_(key_permissions) {
|
| + DCHECK(profile_prefs_);
|
| + DCHECK(profile_policies_);
|
| DCHECK(key_permissions_);
|
| if (state_store_value)
|
| KeyEntriesFromState(*state_store_value);
|
| @@ -73,14 +90,21 @@ KeyPermissions::PermissionsForExtension::~PermissionsForExtension() {
|
|
|
| bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning(
|
| const std::string& public_key_spki_der) {
|
| - KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der);
|
| + KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
|
| + if (matching_entry->sign_once)
|
| + return true;
|
| +
|
| + if (key_permissions_->IsCorporateKey(public_key_spki_der)) {
|
| + LOG(ERROR) << "is corporate key";
|
| + return PolicyAllowsCorporateKeyUsage();
|
| + }
|
|
|
| - return matching_entry->sign_once || matching_entry->sign_unlimited;
|
| + return matching_entry->sign_unlimited;
|
| }
|
|
|
| void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning(
|
| const std::string& public_key_spki_der) {
|
| - KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der);
|
| + KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
|
|
|
| if (!matching_entry->sign_once) {
|
| if (matching_entry->sign_unlimited)
|
| @@ -96,7 +120,7 @@ void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning(
|
|
|
| void KeyPermissions::PermissionsForExtension::RegisterKeyForCorporateUsage(
|
| const std::string& public_key_spki_der) {
|
| - KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der);
|
| + KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
|
|
|
| if (matching_entry->sign_once) {
|
| VLOG(1) << "Key is already allowed for signing, skipping.";
|
| @@ -105,11 +129,27 @@ void KeyPermissions::PermissionsForExtension::RegisterKeyForCorporateUsage(
|
|
|
| matching_entry->sign_once = true;
|
| WriteToStateStore();
|
| +
|
| + DictionaryPrefUpdate update(profile_prefs_, prefs::kPlatformKeys);
|
| +
|
| + scoped_ptr<base::DictionaryValue> new_pref_entry(new base::DictionaryValue);
|
| + new_pref_entry->SetBooleanWithoutPathExpansion(kPrefIsCorporateKey, true);
|
| +
|
| + std::string public_key_spki_der_b64;
|
| + base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
|
| +
|
| + update->SetWithoutPathExpansion(public_key_spki_der_b64,
|
| + new_pref_entry.release());
|
| }
|
|
|
| void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission(
|
| const std::string& public_key_spki_der) {
|
| - KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der);
|
| + if (key_permissions_->IsCorporateKey(public_key_spki_der)) {
|
| + LOG(WARNING) << "Tried to grant permission for corporate key.";
|
| + return;
|
| + }
|
| +
|
| + KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
|
|
|
| if (matching_entry->sign_unlimited) {
|
| VLOG(1) << "Key is already allowed for signing, skipping.";
|
| @@ -120,6 +160,39 @@ void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission(
|
| WriteToStateStore();
|
| }
|
|
|
| +bool KeyPermissions::PermissionsForExtension::PolicyAllowsCorporateKeyUsage() {
|
| + const policy::PolicyMap& policies = profile_policies_->GetPolicies(
|
| + policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()));
|
| + const base::Value* policy_value =
|
| + policies.GetValue(policy::key::kKeyPermissions);
|
| +LOG(ERROR) << "policy value " << policy_value;
|
| + if (!policy_value)
|
| + return false;
|
| +LOG(ERROR) << *policy_value;
|
| +
|
| + const base::DictionaryValue* key_permissions_map = nullptr;
|
| + policy_value->GetAsDictionary(&key_permissions_map);
|
| + if (!key_permissions_map) {
|
| + LOG(ERROR) << "Expected policy to be a dictionary.";
|
| + return false;
|
| + }
|
| +
|
| + const base::DictionaryValue* key_permissions_for_ext = nullptr;
|
| + key_permissions_map->GetDictionaryWithoutPathExpansion(
|
| + extension_id_, &key_permissions_for_ext);
|
| + if (!key_permissions_for_ext) {
|
| +LOG(ERROR) << "no entry for " << extension_id_;
|
| + return false;
|
| +}
|
| +
|
| + bool allow_corporate_key_usage = false;
|
| + key_permissions_for_ext->GetBooleanWithoutPathExpansion(
|
| + kPolicyAllowCorporateKeyUsage, &allow_corporate_key_usage);
|
| +
|
| +LOG(ERROR) << "policy allows corp usage " << allow_corporate_key_usage;
|
| + return allow_corporate_key_usage;
|
| +}
|
| +
|
| void KeyPermissions::PermissionsForExtension::WriteToStateStore() {
|
| key_permissions_->SetPlatformKeysOfExtension(extension_id_,
|
| KeyEntriesToState());
|
| @@ -191,7 +264,7 @@ KeyPermissions::PermissionsForExtension::KeyEntriesToState() {
|
| // Searches |platform_keys| for an entry for |public_key_spki_der_b64|. If found
|
| // returns a pointer to it, otherwise returns null.
|
| KeyPermissions::PermissionsForExtension::KeyEntry*
|
| -KeyPermissions::PermissionsForExtension::GetKeyEntry(
|
| +KeyPermissions::PermissionsForExtension::GetStateStoreEntry(
|
| const std::string& public_key_spki_der) {
|
| std::string public_key_spki_der_b64;
|
| base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
|
| @@ -207,8 +280,18 @@ KeyPermissions::PermissionsForExtension::GetKeyEntry(
|
| return &state_store_entries_.back();
|
| }
|
|
|
| -KeyPermissions::KeyPermissions(extensions::StateStore* extensions_state_store)
|
| - : extensions_state_store_(extensions_state_store), weak_factory_(this) {
|
| +KeyPermissions::KeyPermissions(PrefService* profile_prefs,
|
| + bool profile_is_managed,
|
| + policy::PolicyService* profile_policies,
|
| + extensions::StateStore* extensions_state_store)
|
| + : profile_prefs_(profile_prefs),
|
| + profile_is_managed_(profile_is_managed),
|
| + profile_policies_(profile_policies),
|
| + extensions_state_store_(extensions_state_store),
|
| + weak_factory_(this) {
|
| + DCHECK(profile_prefs_);
|
| + DCHECK(extensions_state_store_);
|
| + DCHECK(!profile_is_managed_ || profile_policies_);
|
| }
|
|
|
| KeyPermissions::~KeyPermissions() {
|
| @@ -223,18 +306,61 @@ void KeyPermissions::GetPermissionsForExtension(
|
| weak_factory_.GetWeakPtr(), extension_id, callback));
|
| }
|
|
|
| -void KeyPermissions::SetPlatformKeysOfExtension(const std::string& extension_id,
|
| - scoped_ptr<base::Value> value) {
|
| - extensions_state_store_->SetExtensionValue(
|
| - extension_id, kStateStorePlatformKeys, value.Pass());
|
| +bool KeyPermissions::CanUserGrantPermissionFor(
|
| + const std::string& public_key_spki_der) {
|
| +LOG(ERROR) << "profile is managed " << profile_is_managed_;
|
| + // As keys cannot be tagged for non-corporate usage, the user can currently
|
| + // not grant any permissions if the profile is managed.
|
| + if (profile_is_managed_)
|
| + return false;
|
| +
|
| + // If this profile is not managed but we find a corporate key, don't allow
|
| + // the user to grant permissions.
|
| + return !IsCorporateKey(public_key_spki_der);
|
| +}
|
| +
|
| +bool KeyPermissions::IsCorporateKey(const std::string& public_key_spki_der) {
|
| + const base::DictionaryValue* prefs_entry = GetPrefsEntry(public_key_spki_der);
|
| + if (prefs_entry) {
|
| + bool is_corporate_key = false;
|
| + prefs_entry->GetBooleanWithoutPathExpansion(kPrefIsCorporateKey,
|
| + &is_corporate_key);
|
| + return is_corporate_key;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void KeyPermissions::RegisterProfilePrefs(
|
| + user_prefs::PrefRegistrySyncable* registry) {
|
| + registry->RegisterDictionaryPref(prefs::kPlatformKeys);
|
| }
|
|
|
| void KeyPermissions::CreatePermissionObjectAndPassToCallback(
|
| const std::string& extension_id,
|
| const PermissionsCallback& callback,
|
| scoped_ptr<base::Value> value) {
|
| - callback.Run(make_scoped_ptr(
|
| - new PermissionsForExtension(extension_id, value.Pass(), this)));
|
| + callback.Run(make_scoped_ptr(new PermissionsForExtension(
|
| + extension_id, value.Pass(), profile_prefs_, profile_policies_, this)));
|
| +}
|
| +
|
| +void KeyPermissions::SetPlatformKeysOfExtension(const std::string& extension_id,
|
| + scoped_ptr<base::Value> value) {
|
| + extensions_state_store_->SetExtensionValue(
|
| + extension_id, kStateStorePlatformKeys, value.Pass());
|
| +}
|
| +
|
| +const base::DictionaryValue* KeyPermissions::GetPrefsEntry(
|
| + const std::string& public_key_spki_der) {
|
| + std::string public_key_spki_der_b64;
|
| + base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
|
| +
|
| + const base::DictionaryValue* platform_keys =
|
| + profile_prefs_->GetDictionary(prefs::kPlatformKeys);
|
| +
|
| + const base::DictionaryValue* key_entry = nullptr;
|
| + platform_keys->GetDictionaryWithoutPathExpansion(public_key_spki_der_b64,
|
| + &key_entry);
|
| + return key_entry;
|
| }
|
|
|
| } // namespace chromeos
|
|
|