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

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: 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 // From older versions of ChromeOS, this key can hold a list of base64 and 28 // From older versions of ChromeOS, this key can hold a list of base64 and
21 // DER-encoded SPKIs. A key can be used for signing at most once if it is part 29 // DER-encoded SPKIs. A key can be used for signing at most once if it is part
22 // of that list 30 // of that list
23 // and removed from that list afterwards. 31 // and removed from that list afterwards.
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 kPrefIsCorporateKey[] = "is_platform_key";
47 const char kPolicyAllowCorporateKeyUsage[] = "allowCorporateKeyUsage";
48
38 } // namespace 49 } // namespace
39 50
40 struct KeyPermissions::PermissionsForExtension::KeyEntry { 51 struct KeyPermissions::PermissionsForExtension::KeyEntry {
41 explicit KeyEntry(const std::string& public_key_spki_der_b64) 52 explicit KeyEntry(const std::string& public_key_spki_der_b64)
42 : spki_b64(public_key_spki_der_b64) {} 53 : spki_b64(public_key_spki_der_b64) {}
43 54
44 // The base64-encoded DER of a X.509 Subject Public Key Info. 55 // The base64-encoded DER of a X.509 Subject Public Key Info.
45 const std::string spki_b64; 56 const std::string spki_b64;
46 57
47 // True if the key can be used once for singing. 58 // True if the key can be used once for singing.
48 // This permission is granted if an extension generated a key using the 59 // This permission is granted if an extension generated a key using the
49 // enterprise.platformKeys API, so that it can build a certification request.. 60 // enterprise.platformKeys API, so that it can build a certification request..
50 // After the first signing operation this permission will be revoked. 61 // After the first signing operation this permission will be revoked.
51 bool sign_once = false; 62 bool sign_once = false;
52 63
53 // True if the key can be used for signing an unlimited number of times. 64 // 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 65 // 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 66 // 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. 67 // This permission is granted until revoked by the user or the policy.
58 bool sign_unlimited = false; 68 bool sign_unlimited = false;
59 }; 69 };
60 70
61 KeyPermissions::PermissionsForExtension::PermissionsForExtension( 71 KeyPermissions::PermissionsForExtension::PermissionsForExtension(
62 const std::string& extension_id, 72 const std::string& extension_id,
63 scoped_ptr<base::Value> state_store_value, 73 scoped_ptr<base::Value> state_store_value,
74 PrefService* profile_prefs,
75 policy::PolicyService* profile_policies,
64 KeyPermissions* key_permissions) 76 KeyPermissions* key_permissions)
65 : extension_id_(extension_id), key_permissions_(key_permissions) { 77 : extension_id_(extension_id),
78 profile_prefs_(profile_prefs),
79 profile_policies_(profile_policies),
80 key_permissions_(key_permissions) {
81 DCHECK(profile_prefs_);
82 DCHECK(profile_policies_);
66 DCHECK(key_permissions_); 83 DCHECK(key_permissions_);
67 if (state_store_value) 84 if (state_store_value)
68 KeyEntriesFromState(*state_store_value); 85 KeyEntriesFromState(*state_store_value);
69 } 86 }
70 87
71 KeyPermissions::PermissionsForExtension::~PermissionsForExtension() { 88 KeyPermissions::PermissionsForExtension::~PermissionsForExtension() {
72 } 89 }
73 90
74 bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning( 91 bool KeyPermissions::PermissionsForExtension::CanUseKeyForSigning(
75 const std::string& public_key_spki_der) { 92 const std::string& public_key_spki_der) {
76 KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der); 93 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
94 if (matching_entry->sign_once)
95 return true;
77 96
78 return matching_entry->sign_once || matching_entry->sign_unlimited; 97 if (key_permissions_->IsCorporateKey(public_key_spki_der)) {
98 LOG(ERROR) << "is corporate key";
99 return PolicyAllowsCorporateKeyUsage();
100 }
101
102 return matching_entry->sign_unlimited;
79 } 103 }
80 104
81 void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning( 105 void KeyPermissions::PermissionsForExtension::SetKeyUsedForSigning(
82 const std::string& public_key_spki_der) { 106 const std::string& public_key_spki_der) {
83 KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der); 107 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
84 108
85 if (!matching_entry->sign_once) { 109 if (!matching_entry->sign_once) {
86 if (matching_entry->sign_unlimited) 110 if (matching_entry->sign_unlimited)
87 VLOG(1) << "Key is already marked as not usable for signing, skipping."; 111 VLOG(1) << "Key is already marked as not usable for signing, skipping.";
88 else 112 else
89 LOG(ERROR) << "Key was not allowed for signing."; 113 LOG(ERROR) << "Key was not allowed for signing.";
90 return; 114 return;
91 } 115 }
92 116
93 matching_entry->sign_once = false; 117 matching_entry->sign_once = false;
94 WriteToStateStore(); 118 WriteToStateStore();
95 } 119 }
96 120
97 void KeyPermissions::PermissionsForExtension::RegisterKeyForCorporateUsage( 121 void KeyPermissions::PermissionsForExtension::RegisterKeyForCorporateUsage(
98 const std::string& public_key_spki_der) { 122 const std::string& public_key_spki_der) {
99 KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der); 123 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
100 124
101 if (matching_entry->sign_once) { 125 if (matching_entry->sign_once) {
102 VLOG(1) << "Key is already allowed for signing, skipping."; 126 VLOG(1) << "Key is already allowed for signing, skipping.";
103 return; 127 return;
104 } 128 }
105 129
106 matching_entry->sign_once = true; 130 matching_entry->sign_once = true;
107 WriteToStateStore(); 131 WriteToStateStore();
132
133 DictionaryPrefUpdate update(profile_prefs_, prefs::kPlatformKeys);
134
135 scoped_ptr<base::DictionaryValue> new_pref_entry(new base::DictionaryValue);
136 new_pref_entry->SetBooleanWithoutPathExpansion(kPrefIsCorporateKey, true);
137
138 std::string public_key_spki_der_b64;
139 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
140
141 update->SetWithoutPathExpansion(public_key_spki_der_b64,
142 new_pref_entry.release());
108 } 143 }
109 144
110 void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission( 145 void KeyPermissions::PermissionsForExtension::SetUserGrantedPermission(
111 const std::string& public_key_spki_der) { 146 const std::string& public_key_spki_der) {
112 KeyEntry* matching_entry = GetKeyEntry(public_key_spki_der); 147 if (key_permissions_->IsCorporateKey(public_key_spki_der)) {
148 LOG(WARNING) << "Tried to grant permission for corporate key.";
149 return;
150 }
151
152 KeyEntry* matching_entry = GetStateStoreEntry(public_key_spki_der);
113 153
114 if (matching_entry->sign_unlimited) { 154 if (matching_entry->sign_unlimited) {
115 VLOG(1) << "Key is already allowed for signing, skipping."; 155 VLOG(1) << "Key is already allowed for signing, skipping.";
116 return; 156 return;
117 } 157 }
118 158
119 matching_entry->sign_unlimited = true; 159 matching_entry->sign_unlimited = true;
120 WriteToStateStore(); 160 WriteToStateStore();
121 } 161 }
122 162
163 bool KeyPermissions::PermissionsForExtension::PolicyAllowsCorporateKeyUsage() {
164 const policy::PolicyMap& policies = profile_policies_->GetPolicies(
165 policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()));
166 const base::Value* policy_value =
167 policies.GetValue(policy::key::kKeyPermissions);
168 LOG(ERROR) << "policy value " << policy_value;
169 if (!policy_value)
170 return false;
171 LOG(ERROR) << *policy_value;
172
173 const base::DictionaryValue* key_permissions_map = nullptr;
174 policy_value->GetAsDictionary(&key_permissions_map);
175 if (!key_permissions_map) {
176 LOG(ERROR) << "Expected policy to be a dictionary.";
177 return false;
178 }
179
180 const base::DictionaryValue* key_permissions_for_ext = nullptr;
181 key_permissions_map->GetDictionaryWithoutPathExpansion(
182 extension_id_, &key_permissions_for_ext);
183 if (!key_permissions_for_ext) {
184 LOG(ERROR) << "no entry for " << extension_id_;
185 return false;
186 }
187
188 bool allow_corporate_key_usage = false;
189 key_permissions_for_ext->GetBooleanWithoutPathExpansion(
190 kPolicyAllowCorporateKeyUsage, &allow_corporate_key_usage);
191
192 LOG(ERROR) << "policy allows corp usage " << allow_corporate_key_usage;
193 return allow_corporate_key_usage;
194 }
195
123 void KeyPermissions::PermissionsForExtension::WriteToStateStore() { 196 void KeyPermissions::PermissionsForExtension::WriteToStateStore() {
124 key_permissions_->SetPlatformKeysOfExtension(extension_id_, 197 key_permissions_->SetPlatformKeysOfExtension(extension_id_,
125 KeyEntriesToState()); 198 KeyEntriesToState());
126 } 199 }
127 200
128 void KeyPermissions::PermissionsForExtension::KeyEntriesFromState( 201 void KeyPermissions::PermissionsForExtension::KeyEntriesFromState(
129 const base::Value& state) { 202 const base::Value& state) {
130 state_store_entries_.clear(); 203 state_store_entries_.clear();
131 204
132 const base::ListValue* entries = nullptr; 205 const base::ListValue* entries = nullptr;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 entry.sign_unlimited); 257 entry.sign_unlimited);
185 } 258 }
186 new_state->Append(new_entry.release()); 259 new_state->Append(new_entry.release());
187 } 260 }
188 return new_state.Pass(); 261 return new_state.Pass();
189 } 262 }
190 263
191 // Searches |platform_keys| for an entry for |public_key_spki_der_b64|. If found 264 // Searches |platform_keys| for an entry for |public_key_spki_der_b64|. If found
192 // returns a pointer to it, otherwise returns null. 265 // returns a pointer to it, otherwise returns null.
193 KeyPermissions::PermissionsForExtension::KeyEntry* 266 KeyPermissions::PermissionsForExtension::KeyEntry*
194 KeyPermissions::PermissionsForExtension::GetKeyEntry( 267 KeyPermissions::PermissionsForExtension::GetStateStoreEntry(
195 const std::string& public_key_spki_der) { 268 const std::string& public_key_spki_der) {
196 std::string public_key_spki_der_b64; 269 std::string public_key_spki_der_b64;
197 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64); 270 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
198 271
199 for (KeyEntry& entry : state_store_entries_) { 272 for (KeyEntry& entry : state_store_entries_) {
200 // For every ASN.1 value there is exactly one DER encoding, so it is fine to 273 // For every ASN.1 value there is exactly one DER encoding, so it is fine to
201 // compare the DER (or its base64 encoding). 274 // compare the DER (or its base64 encoding).
202 if (entry.spki_b64 == public_key_spki_der_b64) 275 if (entry.spki_b64 == public_key_spki_der_b64)
203 return &entry; 276 return &entry;
204 } 277 }
205 278
206 state_store_entries_.push_back(KeyEntry(public_key_spki_der_b64)); 279 state_store_entries_.push_back(KeyEntry(public_key_spki_der_b64));
207 return &state_store_entries_.back(); 280 return &state_store_entries_.back();
208 } 281 }
209 282
210 KeyPermissions::KeyPermissions(extensions::StateStore* extensions_state_store) 283 KeyPermissions::KeyPermissions(PrefService* profile_prefs,
211 : extensions_state_store_(extensions_state_store), weak_factory_(this) { 284 bool profile_is_managed,
285 policy::PolicyService* profile_policies,
286 extensions::StateStore* extensions_state_store)
287 : profile_prefs_(profile_prefs),
288 profile_is_managed_(profile_is_managed),
289 profile_policies_(profile_policies),
290 extensions_state_store_(extensions_state_store),
291 weak_factory_(this) {
292 DCHECK(profile_prefs_);
293 DCHECK(extensions_state_store_);
294 DCHECK(!profile_is_managed_ || profile_policies_);
212 } 295 }
213 296
214 KeyPermissions::~KeyPermissions() { 297 KeyPermissions::~KeyPermissions() {
215 } 298 }
216 299
217 void KeyPermissions::GetPermissionsForExtension( 300 void KeyPermissions::GetPermissionsForExtension(
218 const std::string& extension_id, 301 const std::string& extension_id,
219 const PermissionsCallback& callback) { 302 const PermissionsCallback& callback) {
220 extensions_state_store_->GetExtensionValue( 303 extensions_state_store_->GetExtensionValue(
221 extension_id, kStateStorePlatformKeys, 304 extension_id, kStateStorePlatformKeys,
222 base::Bind(&KeyPermissions::CreatePermissionObjectAndPassToCallback, 305 base::Bind(&KeyPermissions::CreatePermissionObjectAndPassToCallback,
223 weak_factory_.GetWeakPtr(), extension_id, callback)); 306 weak_factory_.GetWeakPtr(), extension_id, callback));
224 } 307 }
225 308
309 bool KeyPermissions::CanUserGrantPermissionFor(
310 const std::string& public_key_spki_der) {
311 LOG(ERROR) << "profile is managed " << profile_is_managed_;
312 // As keys cannot be tagged for non-corporate usage, the user can currently
313 // not grant any permissions if the profile is managed.
314 if (profile_is_managed_)
315 return false;
316
317 // If this profile is not managed but we find a corporate key, don't allow
318 // the user to grant permissions.
319 return !IsCorporateKey(public_key_spki_der);
320 }
321
322 bool KeyPermissions::IsCorporateKey(const std::string& public_key_spki_der) {
323 const base::DictionaryValue* prefs_entry = GetPrefsEntry(public_key_spki_der);
324 if (prefs_entry) {
325 bool is_corporate_key = false;
326 prefs_entry->GetBooleanWithoutPathExpansion(kPrefIsCorporateKey,
327 &is_corporate_key);
328 return is_corporate_key;
329 }
330 return false;
331 }
332
333 void KeyPermissions::RegisterProfilePrefs(
334 user_prefs::PrefRegistrySyncable* registry) {
335 registry->RegisterDictionaryPref(prefs::kPlatformKeys);
336 }
337
338 void KeyPermissions::CreatePermissionObjectAndPassToCallback(
339 const std::string& extension_id,
340 const PermissionsCallback& callback,
341 scoped_ptr<base::Value> value) {
342 callback.Run(make_scoped_ptr(new PermissionsForExtension(
343 extension_id, value.Pass(), profile_prefs_, profile_policies_, this)));
344 }
345
226 void KeyPermissions::SetPlatformKeysOfExtension(const std::string& extension_id, 346 void KeyPermissions::SetPlatformKeysOfExtension(const std::string& extension_id,
227 scoped_ptr<base::Value> value) { 347 scoped_ptr<base::Value> value) {
228 extensions_state_store_->SetExtensionValue( 348 extensions_state_store_->SetExtensionValue(
229 extension_id, kStateStorePlatformKeys, value.Pass()); 349 extension_id, kStateStorePlatformKeys, value.Pass());
230 } 350 }
231 351
232 void KeyPermissions::CreatePermissionObjectAndPassToCallback( 352 const base::DictionaryValue* KeyPermissions::GetPrefsEntry(
233 const std::string& extension_id, 353 const std::string& public_key_spki_der) {
234 const PermissionsCallback& callback, 354 std::string public_key_spki_der_b64;
235 scoped_ptr<base::Value> value) { 355 base::Base64Encode(public_key_spki_der, &public_key_spki_der_b64);
236 callback.Run(make_scoped_ptr( 356
237 new PermissionsForExtension(extension_id, value.Pass(), this))); 357 const base::DictionaryValue* platform_keys =
358 profile_prefs_->GetDictionary(prefs::kPlatformKeys);
359
360 const base::DictionaryValue* key_entry = nullptr;
361 platform_keys->GetDictionaryWithoutPathExpansion(public_key_spki_der_b64,
362 &key_entry);
363 return key_entry;
238 } 364 }
239 365
240 } // namespace chromeos 366 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698