Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chrome/browser/chromeos/platform_keys/key_permissions.cc

Issue 1150373002: platformKeys: Add policy and corporate key tagging. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@key_perm
Patch Set: Rebased. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/platform_keys/key_permissions.h" 5 #include "chrome/browser/chromeos/platform_keys/key_permissions.h"
6 6
7 #include "base/base64.h" 7 #include "base/base64.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/prefs/scoped_user_pref_update.h"
11 #include "base/values.h" 13 #include "base/values.h"
14 #include "chrome/common/pref_names.h"
15 #include "components/policy/core/common/policy_map.h"
16 #include "components/policy/core/common/policy_namespace.h"
17 #include "components/policy/core/common/policy_service.h"
18 #include "components/pref_registry/pref_registry_syncable.h"
12 #include "extensions/browser/state_store.h" 19 #include "extensions/browser/state_store.h"
20 #include "policy/policy_constants.h"
13 21
14 namespace chromeos { 22 namespace chromeos {
15 23
16 namespace { 24 namespace {
17 25
18 // The key at which platform key specific data is stored in each extension's 26 // The key at which platform key specific data is stored in each extension's
19 // state store. 27 // state store.
20 // 28 //
21 // From older versions of ChromeOS, this key can hold a list of base64 and 29 // From older versions of ChromeOS, this key can hold a list of base64 and
22 // DER-encoded SPKIs. A key can be used for signing at most once if it is part 30 // DER-encoded SPKIs. A key can be used for signing at most once if it is part
23 // of that list. 31 // of that list.
24 // 32 //
25 // The current format of data that is written to the PlatformKeys field is a 33 // The current format of data that is written to the PlatformKeys field is a
26 // list of serialized KeyEntry objects: 34 // list of serialized KeyEntry objects:
27 // { 'SPKI': string, 35 // { 'SPKI': string,
28 // 'signOnce': bool, // if not present, defaults to false 36 // 'signOnce': bool, // if not present, defaults to false
29 // 'signUnlimited': bool // if not present, defaults to false 37 // 'signUnlimited': bool // if not present, defaults to false
30 // } 38 // }
31 // 39 //
32 // Do not change this constant as clients will lose their existing state. 40 // Do not change this constant as clients will lose their existing state.
33 const char kStateStorePlatformKeys[] = "PlatformKeys"; 41 const char kStateStorePlatformKeys[] = "PlatformKeys";
34 const char kStateStoreSPKI[] = "SPKI"; 42 const char kStateStoreSPKI[] = "SPKI";
35 const char kStateStoreSignOnce[] = "signOnce"; 43 const char kStateStoreSignOnce[] = "signOnce";
36 const char kStateStoreSignUnlimited[] = "signUnlimited"; 44 const char kStateStoreSignUnlimited[] = "signUnlimited";
37 45
46 const char kPrefKeyUsage[] = "keyUsage";
47 const char kPrefKeyUsageCorporate[] = "corporate";
48 const char kPolicyAllowCorporateKeyUsage[] = "allowCorporateKeyUsage";
49
38 } // namespace 50 } // namespace
39 51
40 struct KeyPermissions::PermissionsForExtension::KeyEntry { 52 struct KeyPermissions::PermissionsForExtension::KeyEntry {
41 explicit KeyEntry(const std::string& public_key_spki_der_b64) 53 explicit KeyEntry(const std::string& public_key_spki_der_b64)
42 : spki_b64(public_key_spki_der_b64) {} 54 : spki_b64(public_key_spki_der_b64) {}
43 55
44 // The base64-encoded DER of a X.509 Subject Public Key Info. 56 // The base64-encoded DER of a X.509 Subject Public Key Info.
45 std::string spki_b64; 57 std::string spki_b64;
46 58
47 // True if the key can be used once for singing. 59 // True if the key can be used once for singing.
48 // This permission is granted if an extension generated a key using the 60 // This permission is granted if an extension generated a key using the
49 // enterprise.platformKeys API, so that it can build a certification request. 61 // enterprise.platformKeys API, so that it can build a certification request.
50 // After the first signing operation this permission will be revoked. 62 // After the first signing operation this permission will be revoked.
51 bool sign_once = false; 63 bool sign_once = false;
52 64
53 // True if the key can be used for signing an unlimited number of times. 65 // True if the key can be used for signing an unlimited number of times.
54 // This permission is granted by the user or by policy to allow the extension 66 // This permission is granted by the user to allow the extension to use the
55 // to use the key for signing through the enterprise.platformKeys or 67 // key for signing through the enterprise.platformKeys or platformKeys API.
56 // platformKeys API.
57 // This permission is granted until revoked by the user or the policy. 68 // This permission is granted until revoked by the user or the policy.
58 bool sign_unlimited = false; 69 bool sign_unlimited = false;
59 }; 70 };
60 71
61 KeyPermissions::PermissionsForExtension::PermissionsForExtension( 72 KeyPermissions::PermissionsForExtension::PermissionsForExtension(
62 const std::string& extension_id, 73 const std::string& extension_id,
63 scoped_ptr<base::Value> state_store_value, 74 scoped_ptr<base::Value> state_store_value,
75 PrefService* profile_prefs,
76 policy::PolicyService* profile_policies,
64 KeyPermissions* key_permissions) 77 KeyPermissions* key_permissions)
65 : extension_id_(extension_id), key_permissions_(key_permissions) { 78 : extension_id_(extension_id),
79 profile_prefs_(profile_prefs),
80 profile_policies_(profile_policies),
81 key_permissions_(key_permissions) {
82 DCHECK(profile_prefs_);
83 DCHECK(profile_policies_);
66 DCHECK(key_permissions_); 84 DCHECK(key_permissions_);
67 if (state_store_value) 85 if (state_store_value)
68 KeyEntriesFromState(*state_store_value); 86 KeyEntriesFromState(*state_store_value);
69 } 87 }
70 88
71 KeyPermissions::PermissionsForExtension::~PermissionsForExtension() { 89 KeyPermissions::PermissionsForExtension::~PermissionsForExtension() {
72 } 90 }
73 91
74 bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning( 92 bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning(
75 const std::string& public_key_spki_der) { 93 const std::string& public_key_spki_der) {
76 std::string public_key_spki_der_b64; 94 std::string public_key_spki_der_b64;
77 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); 95 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
78 96
79 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64); 97 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64);
98 if (matching_entry->sign_once)
99 return true;
80 100
81 return matching_entry->sign_once || matching_entry->sign_unlimited; 101 if (key_permissions_->IsCorporateKey(public_key_spki_der_b64))
102 return PolicyAllowsCorporateKeyUsage();
103
104 return matching_entry->sign_unlimited;
82 } 105 }
83 106
84 void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning( 107 void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning(
85 const std::string& public_key_spki_der) { 108 const std::string& public_key_spki_der) {
86 std::string public_key_spki_der_b64; 109 std::string public_key_spki_der_b64;
87 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); 110 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
88 111
89 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64); 112 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64);
90 113
91 if (!matching_entry->sign_once) { 114 if (!matching_entry->sign_once) {
(...skipping 15 matching lines...) Expand all
107 130
108 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64); 131 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64);
109 132
110 if (matching_entry->sign_once) { 133 if (matching_entry->sign_once) {
111 VLOG(1) << "Key is already allowed for signing, skipping."; 134 VLOG(1) << "Key is already allowed for signing, skipping.";
112 return; 135 return;
113 } 136 }
114 137
115 matching_entry->sign_once = true; 138 matching_entry->sign_once = true;
116 WriteToStateStore(); 139 WriteToStateStore();
140
141 DictionaryPrefUpdate update(profile_prefs_, prefs::kPlatformKeys);
142
143 scoped_ptr<base::DictionaryValue> new_pref_entry(new base::DictionaryValue);
144 new_pref_entry->SetStringWithoutPathExpansion(kPrefKeyUsage,
145 kPrefKeyUsageCorporate);
146
147 update->SetWithoutPathExpansion(public_key_spki_der_b64,
148 new_pref_entry.release());
117 } 149 }
118 150
119 void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission( 151 void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission(
120 const std::string& public_key_spki_der) { 152 const std::string& public_key_spki_der) {
121 std::string public_key_spki_der_b64; 153 std::string public_key_spki_der_b64;
122 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); 154 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
123 155
156 if (key_permissions_->IsCorporateKey(public_key_spki_der_b64)) {
157 LOG(WARNING) << "Tried to grant permission for corporate key.";
158 return;
159 }
160
124 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64); 161 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der_b64);
125 162
126 if (matching_entry->sign_unlimited) { 163 if (matching_entry->sign_unlimited) {
127 VLOG(1) << "Key is already allowed for signing, skipping."; 164 VLOG(1) << "Key is already allowed for signing, skipping.";
128 return; 165 return;
129 } 166 }
130 167
131 matching_entry->sign_unlimited = true; 168 matching_entry->sign_unlimited = true;
132 WriteToStateStore(); 169 WriteToStateStore();
133 } 170 }
134 171
172 bool KeyPermissions::PermissionsForExtension::PolicyAllowsCorporateKeyUsage() {
173 const policy::PolicyMap& policies = profile_policies_->GetPolicies(
174 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()));
175 const base::Value* policy_value =
176 policies.GetValue(policy::key::kKeyPermissions);
177 if (!policy_value)
178 return false;
179
180 const base::DictionaryValue* key_permissions_map = nullptr;
181 policy_value->GetAsDictionary(&key_permissions_map);
182 if (!key_permissions_map) {
183 LOG(ERROR) << "Expected policy to be a dictionary.";
184 return false;
185 }
186
187 const base::DictionaryValue* key_permissions_for_ext = nullptr;
188 key_permissions_map->GetDictionaryWithoutPathExpansion(
189 extension_id_, &key_permissions_for_ext);
190 if (!key_permissions_for_ext)
191 return false;
192
193 bool allow_corporate_key_usage = false;
194 key_permissions_for_ext->GetBooleanWithoutPathExpansion(
195 kPolicyAllowCorporateKeyUsage, &allow_corporate_key_usage);
196
197 VLOG_IF(allow_corporate_key_usage, 2)
198 << "Policy allows usage of corporate keys by extension " << extension_id_;
199 return allow_corporate_key_usage;
200 }
201
135 void KeyPermissions::PermissionsForExtension::WriteToStateStore() { 202 void KeyPermissions::PermissionsForExtension::WriteToStateStore() {
136 key_permissions_->SetPlatformKeysOfExtension(extension_id_, 203 key_permissions_->SetPlatformKeysOfExtension(extension_id_,
137 KeyEntriesToState()); 204 KeyEntriesToState());
138 } 205 }
139 206
140 void KeyPermissions::PermissionsForExtension::KeyEntriesFromState( 207 void KeyPermissions::PermissionsForExtension::KeyEntriesFromState(
141 const base::Value& state) { 208 const base::Value& state) {
142 state_store_entries_.clear(); 209 state_store_entries_.clear();
143 210
144 const base::ListValue* entries = nullptr; 211 const base::ListValue* entries = nullptr;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 // compare the DER (or its base64 encoding). 275 // compare the DER (or its base64 encoding).
209 if (entry.spki_b64 == public_key_spki_der_b64) 276 if (entry.spki_b64 == public_key_spki_der_b64)
210 return &entry; 277 return &entry;
211 } 278 }
212 279
213 state_store_entries_.push_back(KeyEntry(public_key_spki_der_b64)); 280 state_store_entries_.push_back(KeyEntry(public_key_spki_der_b64));
214 return &state_store_entries_.back(); 281 return &state_store_entries_.back();
215 } 282 }
216 283
217 KeyPermissions::KeyPermissions(bool profile_is_managed, 284 KeyPermissions::KeyPermissions(bool profile_is_managed,
285 PrefService* profile_prefs,
286 policy::PolicyService* profile_policies,
218 extensions::StateStore* extensions_state_store) 287 extensions::StateStore* extensions_state_store)
219 : profile_is_managed_(profile_is_managed), 288 : profile_is_managed_(profile_is_managed),
289 profile_prefs_(profile_prefs),
290 profile_policies_(profile_policies),
220 extensions_state_store_(extensions_state_store), 291 extensions_state_store_(extensions_state_store),
221 weak_factory_(this) { 292 weak_factory_(this) {
293 DCHECK(profile_prefs_);
294 DCHECK(extensions_state_store_);
295 DCHECK(!profile_is_managed_ || profile_policies_);
222 } 296 }
223 297
224 KeyPermissions::~KeyPermissions() { 298 KeyPermissions::~KeyPermissions() {
225 } 299 }
226 300
227 void KeyPermissions::GetPermissionsForExtension( 301 void KeyPermissions::GetPermissionsForExtension(
228 const std::string& extension_id, 302 const std::string& extension_id,
229 const PermissionsCallback& callback) { 303 const PermissionsCallback& callback) {
230 extensions_state_store_->GetExtensionValue( 304 extensions_state_store_->GetExtensionValue(
231 extension_id, kStateStorePlatformKeys, 305 extension_id, kStateStorePlatformKeys,
232 base::Bind(&KeyPermissions::CreatePermissionObjectAndPassToCallback, 306 base::Bind(&KeyPermissions::CreatePermissionObjectAndPassToCallback,
233 weak_factory_.GetWeakPtr(), extension_id, callback)); 307 weak_factory_.GetWeakPtr(), extension_id, callback));
234 } 308 }
235 309
236 bool KeyPermissions::CanUserGrantPermissionFor( 310 bool KeyPermissions::CanUserGrantPermissionFor(
237 const std::string& public_key_spki_der) { 311 const std::string& public_key_spki_der) {
238 // As keys cannot be tagged for non-corporate usage, the user can currently 312 // As keys cannot be tagged for non-corporate usage, the user can currently
239 // not grant any permissions if the profile is managed. 313 // not grant any permissions if the profile is managed.
240 return !profile_is_managed_; 314 if (profile_is_managed_)
315 return false;
316
317 std::string public_key_spki_der_b64;
318 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
319
320 // If this profile is not managed but we find a corporate key, don't allow
321 // the user to grant permissions.
322 return !IsCorporateKey(public_key_spki_der_b64);
323 }
324
325 bool KeyPermissions::IsCorporateKey(
326 const std::string& public_key_spki_der_b64) {
327 const base::DictionaryValue* prefs_entry =
328 GetPrefsEntry(public_key_spki_der_b64);
329 if (prefs_entry) {
330 std::string key_usage;
331 prefs_entry->GetStringWithoutPathExpansion(kPrefKeyUsage, &key_usage);
332 return key_usage == kPrefKeyUsageCorporate;
333 }
334 return false;
335 }
336
337 void KeyPermissions::RegisterProfilePrefs(
338 user_prefs::PrefRegistrySyncable* registry) {
339 registry->RegisterDictionaryPref(prefs::kPlatformKeys);
340 }
341
342 void KeyPermissions::CreatePermissionObjectAndPassToCallback(
343 const std::string& extension_id,
344 const PermissionsCallback& callback,
345 scoped_ptr<base::Value> value) {
346 callback.Run(make_scoped_ptr(new PermissionsForExtension(
347 extension_id, value.Pass(), profile_prefs_, profile_policies_, this)));
241 } 348 }
242 349
243 void KeyPermissions::SetPlatformKeysOfExtension(const std::string& extension_id, 350 void KeyPermissions::SetPlatformKeysOfExtension(const std::string& extension_id,
244 scoped_ptr<base::Value> value) { 351 scoped_ptr<base::Value> value) {
245 extensions_state_store_->SetExtensionValue( 352 extensions_state_store_->SetExtensionValue(
246 extension_id, kStateStorePlatformKeys, value.Pass()); 353 extension_id, kStateStorePlatformKeys, value.Pass());
247 } 354 }
248 355
249 void KeyPermissions::CreatePermissionObjectAndPassToCallback( 356 const base::DictionaryValue* KeyPermissions::GetPrefsEntry(
250 const std::string& extension_id, 357 const std::string& public_key_spki_der_b64) {
251 const PermissionsCallback& callback, 358 const base::DictionaryValue* platform_keys =
252 scoped_ptr<base::Value> value) { 359 profile_prefs_->GetDictionary(prefs::kPlatformKeys);
253 callback.Run(make_scoped_ptr( 360
254 new PermissionsForExtension(extension_id, value.Pass(), this))); 361 const base::DictionaryValue* key_entry = nullptr;
362 platform_keys->GetDictionaryWithoutPathExpansion(public_key_spki_der_b64,
363 &key_entry);
364 return key_entry;
255 } 365 }
256 366
257 } // namespace chromeos 367 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698