OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "platform_verification_flow.h" | 5 #include "platform_verification_flow.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/prefs/pref_service.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
Mattias Nissler (ping if slow)
2013/09/03 14:31:25
required?
Darren Krahn
2013/09/04 12:35:05
Done.
| |
8 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" | 10 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" |
9 #include "chrome/browser/chromeos/login/user_manager.h" | 11 #include "chrome/browser/chromeos/login/user_manager.h" |
10 #include "chrome/browser/chromeos/settings/cros_settings.h" | 12 #include "chrome/browser/chromeos/settings/cros_settings.h" |
13 #include "chrome/browser/infobars/confirm_infobar_delegate.h" | |
Mattias Nissler (ping if slow)
2013/09/03 14:31:25
required?
Darren Krahn
2013/09/04 12:35:05
Done.
| |
14 #include "chrome/browser/prefs/scoped_user_pref_update.h" | |
15 #include "chrome/common/pref_names.h" | |
11 #include "chromeos/attestation/attestation_flow.h" | 16 #include "chromeos/attestation/attestation_flow.h" |
12 #include "chromeos/cryptohome/async_method_caller.h" | 17 #include "chromeos/cryptohome/async_method_caller.h" |
13 #include "chromeos/dbus/cryptohome_client.h" | 18 #include "chromeos/dbus/cryptohome_client.h" |
14 #include "chromeos/dbus/dbus_thread_manager.h" | 19 #include "chromeos/dbus/dbus_thread_manager.h" |
20 #include "components/user_prefs/pref_registry_syncable.h" | |
21 #include "components/user_prefs/user_prefs.h" | |
15 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
16 #include "content/public/browser/web_contents.h" | 23 #include "content/public/browser/web_contents.h" |
17 | 24 |
18 namespace { | 25 namespace { |
19 // A callback method to handle DBus errors. | 26 // A callback method to handle DBus errors. |
20 void DBusCallback(const base::Callback<void(bool)>& on_success, | 27 void DBusCallback(const base::Callback<void(bool)>& on_success, |
21 const base::Closure& on_failure, | 28 const base::Closure& on_failure, |
22 chromeos::DBusMethodCallStatus call_status, | 29 chromeos::DBusMethodCallStatus call_status, |
23 bool result) { | 30 bool result) { |
24 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS) { | 31 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS) { |
(...skipping 25 matching lines...) Expand all Loading... | |
50 | 57 |
51 PlatformVerificationFlow::~PlatformVerificationFlow() { | 58 PlatformVerificationFlow::~PlatformVerificationFlow() { |
52 } | 59 } |
53 | 60 |
54 void PlatformVerificationFlow::ChallengePlatformKey( | 61 void PlatformVerificationFlow::ChallengePlatformKey( |
55 content::WebContents* web_contents, | 62 content::WebContents* web_contents, |
56 const std::string& service_id, | 63 const std::string& service_id, |
57 const std::string& challenge, | 64 const std::string& challenge, |
58 const ChallengeCallback& callback) { | 65 const ChallengeCallback& callback) { |
59 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 66 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
60 if (delegate_->IsAttestationDisabled()) { | 67 if (!IsAttestationEnabled(web_contents)) { |
61 LOG(INFO) << "PlatformVerificationFlow: Feature disabled."; | 68 LOG(INFO) << "PlatformVerificationFlow: Feature disabled."; |
62 callback.Run(POLICY_REJECTED, std::string(), std::string()); | 69 callback.Run(POLICY_REJECTED, std::string(), std::string()); |
63 return; | 70 return; |
64 } | 71 } |
65 BoolDBusMethodCallback dbus_callback = base::Bind( | 72 BoolDBusMethodCallback dbus_callback = base::Bind( |
66 &DBusCallback, | 73 &DBusCallback, |
67 base::Bind(&PlatformVerificationFlow::CheckConsent, | 74 base::Bind(&PlatformVerificationFlow::CheckConsent, |
68 weak_factory_.GetWeakPtr(), | 75 weak_factory_.GetWeakPtr(), |
69 web_contents, | 76 web_contents, |
70 service_id, | 77 service_id, |
71 challenge, | 78 challenge, |
72 callback), | 79 callback), |
73 base::Bind(callback, INTERNAL_ERROR, std::string(), std::string())); | 80 base::Bind(callback, INTERNAL_ERROR, std::string(), std::string())); |
74 cryptohome_client_->TpmAttestationIsEnrolled(dbus_callback); | 81 cryptohome_client_->TpmAttestationIsEnrolled(dbus_callback); |
75 } | 82 } |
76 | 83 |
77 void PlatformVerificationFlow::CheckConsent(content::WebContents* web_contents, | 84 void PlatformVerificationFlow::CheckConsent(content::WebContents* web_contents, |
78 const std::string& service_id, | 85 const std::string& service_id, |
79 const std::string& challenge, | 86 const std::string& challenge, |
80 const ChallengeCallback& callback, | 87 const ChallengeCallback& callback, |
81 bool attestation_enrolled) { | 88 bool attestation_enrolled) { |
82 ConsentType consent_type = CONSENT_TYPE_NONE; | 89 ConsentType consent_type = CONSENT_TYPE_NONE; |
83 if (!attestation_enrolled) { | 90 if (!attestation_enrolled || IsFirstUse(web_contents)) { |
84 consent_type = CONSENT_TYPE_ATTESTATION; | 91 consent_type = CONSENT_TYPE_ATTESTATION; |
85 } else if (delegate_->IsOriginConsentRequired(web_contents)) { | 92 } else if (IsAlwaysAskRequired(web_contents)) { |
86 consent_type = CONSENT_TYPE_ORIGIN; | |
87 } else if (delegate_->IsAlwaysAskRequired(web_contents)) { | |
88 consent_type = CONSENT_TYPE_ALWAYS; | 93 consent_type = CONSENT_TYPE_ALWAYS; |
89 } | 94 } |
90 Delegate::ConsentCallback consent_callback = base::Bind( | 95 Delegate::ConsentCallback consent_callback = base::Bind( |
91 &PlatformVerificationFlow::OnConsentResponse, | 96 &PlatformVerificationFlow::OnConsentResponse, |
92 weak_factory_.GetWeakPtr(), | 97 weak_factory_.GetWeakPtr(), |
93 web_contents, | 98 web_contents, |
94 service_id, | 99 service_id, |
95 challenge, | 100 challenge, |
96 callback, | 101 callback, |
97 consent_type); | 102 consent_type); |
98 if (consent_type == CONSENT_TYPE_NONE) { | 103 if (consent_type == CONSENT_TYPE_NONE) { |
99 consent_callback.Run(CONSENT_RESPONSE_NONE); | 104 consent_callback.Run(CONSENT_RESPONSE_NONE); |
100 } else { | 105 } else { |
101 delegate_->ShowConsentPrompt(consent_type, | 106 delegate_->ShowConsentPrompt(consent_type, |
102 web_contents, | 107 web_contents, |
103 consent_callback); | 108 consent_callback); |
104 } | 109 } |
105 } | 110 } |
106 | 111 |
112 void PlatformVerificationFlow::RegisterProfilePrefs( | |
113 user_prefs::PrefRegistrySyncable* prefs) { | |
114 prefs->RegisterBooleanPref(prefs::kRAConsentFirstTime, | |
115 false, | |
116 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
117 prefs->RegisterDictionaryPref( | |
118 prefs::kRAConsentDomains, | |
119 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
120 prefs->RegisterBooleanPref(prefs::kRAConsentAlways, | |
121 false, | |
122 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | |
123 } | |
124 | |
107 void PlatformVerificationFlow::OnConsentResponse( | 125 void PlatformVerificationFlow::OnConsentResponse( |
108 content::WebContents* web_contents, | 126 content::WebContents* web_contents, |
109 const std::string& service_id, | 127 const std::string& service_id, |
110 const std::string& challenge, | 128 const std::string& challenge, |
111 const ChallengeCallback& callback, | 129 const ChallengeCallback& callback, |
112 ConsentType consent_type, | 130 ConsentType consent_type, |
113 ConsentResponse consent_response) { | 131 ConsentResponse consent_response) { |
114 if (consent_type != CONSENT_TYPE_NONE) { | 132 if (consent_type != CONSENT_TYPE_NONE) { |
115 if (consent_response == CONSENT_RESPONSE_NONE) { | 133 if (consent_response == CONSENT_RESPONSE_NONE) { |
116 // No user response - do not proceed and do not modify any settings. | 134 // No user response - do not proceed and do not modify any settings. |
117 LOG(WARNING) << "PlatformVerificationFlow: No response from user."; | 135 LOG(WARNING) << "PlatformVerificationFlow: No response from user."; |
118 callback.Run(USER_REJECTED, std::string(), std::string()); | 136 callback.Run(USER_REJECTED, std::string(), std::string()); |
119 return; | 137 return; |
120 } | 138 } |
121 if (!delegate_->UpdateSettings(web_contents, | 139 if (!UpdateSettings(web_contents, consent_type, consent_response)) { |
122 consent_type, | |
123 consent_response)) { | |
124 callback.Run(INTERNAL_ERROR, std::string(), std::string()); | 140 callback.Run(INTERNAL_ERROR, std::string(), std::string()); |
125 return; | 141 return; |
126 } | 142 } |
127 if (consent_response == CONSENT_RESPONSE_DENY) { | 143 if (consent_response == CONSENT_RESPONSE_DENY) { |
128 LOG(INFO) << "PlatformVerificationFlow: User rejected request."; | 144 LOG(INFO) << "PlatformVerificationFlow: User rejected request."; |
129 callback.Run(USER_REJECTED, std::string(), std::string()); | 145 callback.Run(USER_REJECTED, std::string(), std::string()); |
130 return; | 146 return; |
131 } | 147 } |
132 } | 148 } |
133 | 149 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 const std::string& response_data) { | 194 const std::string& response_data) { |
179 if (!operation_success) { | 195 if (!operation_success) { |
180 LOG(ERROR) << "PlatformVerificationFlow: Failed to sign challenge."; | 196 LOG(ERROR) << "PlatformVerificationFlow: Failed to sign challenge."; |
181 callback.Run(INTERNAL_ERROR, std::string(), std::string()); | 197 callback.Run(INTERNAL_ERROR, std::string(), std::string()); |
182 return; | 198 return; |
183 } | 199 } |
184 LOG(INFO) << "PlatformVerificationFlow: Platform successfully verified."; | 200 LOG(INFO) << "PlatformVerificationFlow: Platform successfully verified."; |
185 callback.Run(SUCCESS, response_data, certificate); | 201 callback.Run(SUCCESS, response_data, certificate); |
186 } | 202 } |
187 | 203 |
204 PrefService* PlatformVerificationFlow::GetPrefs( | |
205 content::WebContents* web_contents) { | |
206 if (testing_prefs_) | |
207 return testing_prefs_; | |
208 return user_prefs::UserPrefs::Get(web_contents->GetBrowserContext()); | |
209 } | |
210 | |
211 const GURL& PlatformVerificationFlow::GetURL( | |
212 content::WebContents* web_contents) { | |
213 if (!testing_url_.is_empty()) | |
214 return testing_url_; | |
215 return web_contents->GetLastCommittedURL(); | |
216 } | |
217 | |
218 bool PlatformVerificationFlow::IsAttestationEnabled( | |
219 content::WebContents* web_contents) { | |
220 // Check the device policy for the feature. | |
221 bool enabled_for_device = false; | |
222 if (!CrosSettings::Get()->GetBoolean(kAttestationForContentProtectionEnabled, | |
223 &enabled_for_device)) { | |
224 LOG(ERROR) << "Failed to get device setting."; | |
225 return false; | |
226 } | |
227 if (!enabled_for_device) | |
228 return false; | |
229 | |
230 // Check the user preference for the feature. | |
231 PrefService* pref_service = GetPrefs(web_contents); | |
232 if (!pref_service) { | |
233 LOG(ERROR) << "Failed to get user prefs."; | |
234 return false; | |
235 } | |
236 if (!pref_service->GetBoolean(prefs::kEnableDRM)) | |
237 return false; | |
238 | |
239 // Check the user preference for this domain. | |
240 bool enabled_for_domain = false; | |
241 bool found = FindDomainPref(web_contents, &enabled_for_domain); | |
242 return (!found || enabled_for_domain); | |
243 } | |
244 | |
245 bool PlatformVerificationFlow::IsFirstUse(content::WebContents* web_contents) { | |
246 PrefService* pref_service = GetPrefs(web_contents); | |
247 if (!pref_service) { | |
248 LOG(ERROR) << "Failed to get user prefs."; | |
249 return true; | |
250 } | |
251 return !pref_service->GetBoolean(prefs::kRAConsentFirstTime); | |
252 } | |
253 | |
254 bool PlatformVerificationFlow::IsAlwaysAskRequired( | |
255 content::WebContents* web_contents) { | |
256 PrefService* pref_service = GetPrefs(web_contents); | |
257 if (!pref_service) { | |
258 LOG(ERROR) << "Failed to get user prefs."; | |
259 return false; | |
Mattias Nissler (ping if slow)
2013/09/03 14:31:25
Shouldn't we default to true here?
Darren Krahn
2013/09/04 12:35:05
Done.
| |
260 } | |
261 if (!pref_service->GetBoolean(prefs::kRAConsentAlways)) | |
262 return false; | |
263 // Show the consent UI if the user has not already explicitly allowed or | |
264 // denied for this domain. | |
265 return !FindDomainPref(web_contents, NULL); | |
266 } | |
267 | |
268 bool PlatformVerificationFlow::UpdateSettings( | |
269 content::WebContents* web_contents, | |
270 ConsentType consent_type, | |
271 ConsentResponse consent_response) { | |
272 PrefService* pref_service = GetPrefs(web_contents); | |
273 if (!pref_service) { | |
274 LOG(ERROR) << "Failed to get user prefs."; | |
275 return false; | |
276 } | |
277 if (consent_type == CONSENT_TYPE_ATTESTATION) { | |
278 if (consent_response == CONSENT_RESPONSE_DENY) { | |
279 pref_service->SetBoolean(prefs::kEnableDRM, false); | |
280 } else if (consent_response == CONSENT_RESPONSE_ALLOW) { | |
281 pref_service->SetBoolean(prefs::kRAConsentFirstTime, true); | |
282 RecordDomainConsent(web_contents, true); | |
283 } else if (consent_response == CONSENT_RESPONSE_ALWAYS_ASK) { | |
284 pref_service->SetBoolean(prefs::kRAConsentFirstTime, true); | |
285 pref_service->SetBoolean(prefs::kRAConsentAlways, true); | |
286 RecordDomainConsent(web_contents, true); | |
287 } | |
288 } else if (consent_type == CONSENT_TYPE_ALWAYS) { | |
289 bool allowed = (consent_response == CONSENT_RESPONSE_ALLOW || | |
290 consent_response == CONSENT_RESPONSE_ALWAYS_ASK); | |
291 RecordDomainConsent(web_contents, allowed); | |
292 } | |
293 return true; | |
294 } | |
295 | |
296 bool PlatformVerificationFlow::FindDomainPref( | |
Mattias Nissler (ping if slow)
2013/09/03 14:31:25
This should probably be GetDomainPref
Darren Krahn
2013/09/04 12:35:05
Done.
| |
297 content::WebContents* web_contents, | |
298 bool* pref_value) { | |
299 PrefService* pref_service = GetPrefs(web_contents); | |
300 CHECK(pref_service); | |
301 base::DictionaryValue::Iterator iter( | |
302 *pref_service->GetDictionary(prefs::kRAConsentDomains)); | |
303 const GURL& url = GetURL(web_contents); | |
304 while (!iter.IsAtEnd()) { | |
305 if (url.DomainIs(iter.key().c_str())) { | |
306 if (pref_value) { | |
307 if (!iter.value().GetAsBoolean(pref_value)) { | |
308 LOG(ERROR) << "Unexpected pref type."; | |
309 *pref_value = false; | |
310 } | |
311 } | |
312 return true; | |
313 } | |
314 iter.Advance(); | |
315 } | |
316 return false; | |
317 } | |
318 | |
319 void PlatformVerificationFlow::RecordDomainConsent( | |
320 content::WebContents* web_contents, | |
321 bool allow_domain) { | |
322 PrefService* pref_service = GetPrefs(web_contents); | |
323 CHECK(pref_service); | |
324 DictionaryPrefUpdate updater(pref_service, prefs::kRAConsentDomains); | |
325 const GURL& url = GetURL(web_contents); | |
326 updater->SetBoolean(url.host(), allow_domain); | |
327 } | |
328 | |
188 } // namespace attestation | 329 } // namespace attestation |
189 } // namespace chromeos | 330 } // namespace chromeos |
OLD | NEW |