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/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 DefaultDelegate() {} | 69 DefaultDelegate() {} |
70 virtual ~DefaultDelegate() {} | 70 virtual ~DefaultDelegate() {} |
71 | 71 |
72 virtual void ShowConsentPrompt( | 72 virtual void ShowConsentPrompt( |
73 content::WebContents* web_contents, | 73 content::WebContents* web_contents, |
74 const PlatformVerificationFlow::Delegate::ConsentCallback& callback) | 74 const PlatformVerificationFlow::Delegate::ConsentCallback& callback) |
75 OVERRIDE { | 75 OVERRIDE { |
76 PlatformVerificationDialog::ShowDialog(web_contents, callback); | 76 PlatformVerificationDialog::ShowDialog(web_contents, callback); |
77 } | 77 } |
78 | 78 |
| 79 virtual PrefService* GetPrefs(content::WebContents* web_contents) OVERRIDE { |
| 80 return user_prefs::UserPrefs::Get(web_contents->GetBrowserContext()); |
| 81 } |
| 82 |
| 83 virtual const GURL& GetURL(content::WebContents* web_contents) OVERRIDE { |
| 84 const GURL& url = web_contents->GetLastCommittedURL(); |
| 85 if (!url.is_valid()) |
| 86 return web_contents->GetVisibleURL(); |
| 87 return url; |
| 88 } |
| 89 |
| 90 virtual User* GetUser(content::WebContents* web_contents) OVERRIDE { |
| 91 return UserManager::Get()->GetUserByProfile( |
| 92 Profile::FromBrowserContext(web_contents->GetBrowserContext())); |
| 93 } |
| 94 |
| 95 virtual HostContentSettingsMap* GetContentSettings( |
| 96 content::WebContents* web_contents) OVERRIDE { |
| 97 return Profile::FromBrowserContext(web_contents->GetBrowserContext())-> |
| 98 GetHostContentSettingsMap(); |
| 99 } |
| 100 |
| 101 virtual bool IsGuestOrIncognito(content::WebContents* web_contents) OVERRIDE { |
| 102 Profile* profile = |
| 103 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 104 return (profile->IsOffTheRecord() || profile->IsGuestSession()); |
| 105 } |
| 106 |
79 private: | 107 private: |
80 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); | 108 DISALLOW_COPY_AND_ASSIGN(DefaultDelegate); |
81 }; | 109 }; |
82 | 110 |
83 PlatformVerificationFlow::ChallengeContext::ChallengeContext( | 111 PlatformVerificationFlow::ChallengeContext::ChallengeContext( |
84 content::WebContents* web_contents, | 112 content::WebContents* web_contents, |
85 const std::string& service_id, | 113 const std::string& service_id, |
86 const std::string& challenge, | 114 const std::string& challenge, |
87 const ChallengeCallback& callback) | 115 const ChallengeCallback& callback) |
88 : web_contents(web_contents), | 116 : web_contents(web_contents), |
89 service_id(service_id), | 117 service_id(service_id), |
90 challenge(challenge), | 118 challenge(challenge), |
91 callback(callback) {} | 119 callback(callback) {} |
92 | 120 |
93 PlatformVerificationFlow::ChallengeContext::~ChallengeContext() {} | 121 PlatformVerificationFlow::ChallengeContext::~ChallengeContext() {} |
94 | 122 |
95 PlatformVerificationFlow::PlatformVerificationFlow() | 123 PlatformVerificationFlow::PlatformVerificationFlow() |
96 : attestation_flow_(NULL), | 124 : attestation_flow_(NULL), |
97 async_caller_(cryptohome::AsyncMethodCaller::GetInstance()), | 125 async_caller_(cryptohome::AsyncMethodCaller::GetInstance()), |
98 cryptohome_client_(DBusThreadManager::Get()->GetCryptohomeClient()), | 126 cryptohome_client_(DBusThreadManager::Get()->GetCryptohomeClient()), |
99 user_manager_(UserManager::Get()), | |
100 delegate_(NULL), | 127 delegate_(NULL), |
101 testing_prefs_(NULL), | |
102 testing_content_settings_(NULL), | |
103 timeout_delay_(base::TimeDelta::FromSeconds(kTimeoutInSeconds)) { | 128 timeout_delay_(base::TimeDelta::FromSeconds(kTimeoutInSeconds)) { |
104 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 129 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
105 scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); | 130 scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); |
106 default_attestation_flow_.reset(new AttestationFlow( | 131 default_attestation_flow_.reset(new AttestationFlow( |
107 async_caller_, | 132 async_caller_, |
108 cryptohome_client_, | 133 cryptohome_client_, |
109 attestation_ca_client.Pass())); | 134 attestation_ca_client.Pass())); |
110 attestation_flow_ = default_attestation_flow_.get(); | 135 attestation_flow_ = default_attestation_flow_.get(); |
111 default_delegate_.reset(new DefaultDelegate()); | 136 default_delegate_.reset(new DefaultDelegate()); |
112 delegate_ = default_delegate_.get(); | 137 delegate_ = default_delegate_.get(); |
113 } | 138 } |
114 | 139 |
115 PlatformVerificationFlow::PlatformVerificationFlow( | 140 PlatformVerificationFlow::PlatformVerificationFlow( |
116 AttestationFlow* attestation_flow, | 141 AttestationFlow* attestation_flow, |
117 cryptohome::AsyncMethodCaller* async_caller, | 142 cryptohome::AsyncMethodCaller* async_caller, |
118 CryptohomeClient* cryptohome_client, | 143 CryptohomeClient* cryptohome_client, |
119 UserManager* user_manager, | |
120 Delegate* delegate) | 144 Delegate* delegate) |
121 : attestation_flow_(attestation_flow), | 145 : attestation_flow_(attestation_flow), |
122 async_caller_(async_caller), | 146 async_caller_(async_caller), |
123 cryptohome_client_(cryptohome_client), | 147 cryptohome_client_(cryptohome_client), |
124 user_manager_(user_manager), | |
125 delegate_(delegate), | 148 delegate_(delegate), |
126 testing_prefs_(NULL), | |
127 testing_content_settings_(NULL), | |
128 timeout_delay_(base::TimeDelta::FromSeconds(kTimeoutInSeconds)) { | 149 timeout_delay_(base::TimeDelta::FromSeconds(kTimeoutInSeconds)) { |
129 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 150 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 151 if (!delegate_) { |
| 152 default_delegate_.reset(new DefaultDelegate()); |
| 153 delegate_ = default_delegate_.get(); |
| 154 } |
130 } | 155 } |
131 | 156 |
132 PlatformVerificationFlow::~PlatformVerificationFlow() { | 157 PlatformVerificationFlow::~PlatformVerificationFlow() { |
133 } | 158 } |
134 | 159 |
135 void PlatformVerificationFlow::ChallengePlatformKey( | 160 void PlatformVerificationFlow::ChallengePlatformKey( |
136 content::WebContents* web_contents, | 161 content::WebContents* web_contents, |
137 const std::string& service_id, | 162 const std::string& service_id, |
138 const std::string& challenge, | 163 const std::string& challenge, |
139 const ChallengeCallback& callback) { | 164 const ChallengeCallback& callback) { |
140 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 165 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
141 if (!GetURL(web_contents).is_valid()) { | 166 if (!delegate_->GetURL(web_contents).is_valid()) { |
142 LOG(WARNING) << "PlatformVerificationFlow: Invalid URL."; | 167 LOG(WARNING) << "PlatformVerificationFlow: Invalid URL."; |
143 ReportError(callback, INTERNAL_ERROR); | 168 ReportError(callback, INTERNAL_ERROR); |
144 return; | 169 return; |
145 } | 170 } |
146 if (!IsAttestationEnabled(web_contents)) { | 171 if (!IsAttestationEnabled(web_contents)) { |
147 ReportError(callback, POLICY_REJECTED); | 172 ReportError(callback, POLICY_REJECTED); |
148 return; | 173 return; |
149 } | 174 } |
150 // A platform key must be bound to a user. They are not allowed in incognito | 175 // A platform key must be bound to a user. They are not allowed in incognito |
151 // or guest mode. | 176 // or guest mode. |
152 if (IsGuestOrIncognito(web_contents)) { | 177 if (delegate_->IsGuestOrIncognito(web_contents)) { |
153 ReportError(callback, PLATFORM_NOT_VERIFIED); | 178 ReportError(callback, PLATFORM_NOT_VERIFIED); |
154 return; | 179 return; |
155 } | 180 } |
156 ChallengeContext context(web_contents, service_id, challenge, callback); | 181 ChallengeContext context(web_contents, service_id, challenge, callback); |
157 BoolDBusMethodCallback dbus_callback = base::Bind( | 182 BoolDBusMethodCallback dbus_callback = base::Bind( |
158 &DBusCallback, | 183 &DBusCallback, |
159 base::Bind(&PlatformVerificationFlow::CheckConsent, this, context), | 184 base::Bind(&PlatformVerificationFlow::CheckConsent, this, context), |
160 base::Bind(&ReportError, callback, INTERNAL_ERROR)); | 185 base::Bind(&ReportError, callback, INTERNAL_ERROR)); |
161 cryptohome_client_->TpmAttestationIsEnrolled(dbus_callback); | 186 cryptohome_client_->TpmAttestationIsEnrolled(dbus_callback); |
162 } | 187 } |
163 | 188 |
164 void PlatformVerificationFlow::CheckConsent(const ChallengeContext& context, | 189 void PlatformVerificationFlow::CheckConsent(const ChallengeContext& context, |
165 bool attestation_enrolled) { | 190 bool attestation_enrolled) { |
166 PrefService* pref_service = GetPrefs(context.web_contents); | 191 PrefService* pref_service = delegate_->GetPrefs(context.web_contents); |
167 if (!pref_service) { | 192 if (!pref_service) { |
168 LOG(ERROR) << "Failed to get user prefs."; | 193 LOG(ERROR) << "Failed to get user prefs."; |
169 ReportError(context.callback, INTERNAL_ERROR); | 194 ReportError(context.callback, INTERNAL_ERROR); |
170 return; | 195 return; |
171 } | 196 } |
172 bool consent_required = ( | 197 bool consent_required = ( |
173 // Consent required if attestation has never been enrolled on this device. | 198 // Consent required if attestation has never been enrolled on this device. |
174 !attestation_enrolled || | 199 !attestation_enrolled || |
175 // Consent required if this is the first use of attestation for content | 200 // Consent required if this is the first use of attestation for content |
176 // protection on this device. | 201 // protection on this device. |
177 !pref_service->GetBoolean(prefs::kRAConsentFirstTime) || | 202 !pref_service->GetBoolean(prefs::kRAConsentFirstTime) || |
178 // Consent required if consent has never been given for this domain. | 203 // Consent required if consent has never been given for this domain. |
179 !GetDomainPref(GetContentSettings(context.web_contents), | 204 !GetDomainPref(delegate_->GetContentSettings(context.web_contents), |
180 GetURL(context.web_contents), | 205 delegate_->GetURL(context.web_contents), |
181 NULL)); | 206 NULL)); |
182 | |
183 Delegate::ConsentCallback consent_callback = base::Bind( | 207 Delegate::ConsentCallback consent_callback = base::Bind( |
184 &PlatformVerificationFlow::OnConsentResponse, | 208 &PlatformVerificationFlow::OnConsentResponse, |
185 this, | 209 this, |
186 context, | 210 context, |
187 consent_required); | 211 consent_required); |
188 if (consent_required) | 212 if (consent_required) |
189 delegate_->ShowConsentPrompt(context.web_contents, consent_callback); | 213 delegate_->ShowConsentPrompt(context.web_contents, consent_callback); |
190 else | 214 else |
191 consent_callback.Run(CONSENT_RESPONSE_NONE); | 215 consent_callback.Run(CONSENT_RESPONSE_NONE); |
192 } | 216 } |
(...skipping 26 matching lines...) Expand all Loading... |
219 ReportError(context.callback, USER_REJECTED); | 243 ReportError(context.callback, USER_REJECTED); |
220 return; | 244 return; |
221 } else if (consent_response == CONSENT_RESPONSE_ALLOW) { | 245 } else if (consent_response == CONSENT_RESPONSE_ALLOW) { |
222 content::RecordAction( | 246 content::RecordAction( |
223 content::UserMetricsAction("PlatformVerificationAccepted")); | 247 content::UserMetricsAction("PlatformVerificationAccepted")); |
224 } | 248 } |
225 } | 249 } |
226 | 250 |
227 // At this point all user interaction is complete and we can proceed with the | 251 // At this point all user interaction is complete and we can proceed with the |
228 // certificate request. | 252 // certificate request. |
229 chromeos::User* user = GetUser(context.web_contents); | 253 chromeos::User* user = delegate_->GetUser(context.web_contents); |
230 if (!user) { | 254 if (!user) { |
231 ReportError(context.callback, INTERNAL_ERROR); | 255 ReportError(context.callback, INTERNAL_ERROR); |
232 LOG(ERROR) << "Profile does not map to a valid user."; | 256 LOG(ERROR) << "Profile does not map to a valid user."; |
233 return; | 257 return; |
234 } | 258 } |
235 | 259 |
236 GetCertificate(context, user->email(), false /* Don't force a new key */); | 260 GetCertificate(context, user->email(), false /* Don't force a new key */); |
237 } | 261 } |
238 | 262 |
239 void PlatformVerificationFlow::GetCertificate(const ChallengeContext& context, | 263 void PlatformVerificationFlow::GetCertificate(const ChallengeContext& context, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 LOG(ERROR) << "PlatformVerificationFlow: Failed to parse response data."; | 345 LOG(ERROR) << "PlatformVerificationFlow: Failed to parse response data."; |
322 ReportError(context.callback, INTERNAL_ERROR); | 346 ReportError(context.callback, INTERNAL_ERROR); |
323 return; | 347 return; |
324 } | 348 } |
325 context.callback.Run(SUCCESS, | 349 context.callback.Run(SUCCESS, |
326 signed_data_pb.data(), | 350 signed_data_pb.data(), |
327 signed_data_pb.signature(), | 351 signed_data_pb.signature(), |
328 certificate); | 352 certificate); |
329 } | 353 } |
330 | 354 |
331 PrefService* PlatformVerificationFlow::GetPrefs( | |
332 content::WebContents* web_contents) { | |
333 if (testing_prefs_) | |
334 return testing_prefs_; | |
335 return user_prefs::UserPrefs::Get(web_contents->GetBrowserContext()); | |
336 } | |
337 | |
338 const GURL& PlatformVerificationFlow::GetURL( | |
339 content::WebContents* web_contents) { | |
340 if (!testing_url_.is_empty()) | |
341 return testing_url_; | |
342 const GURL& url = web_contents->GetLastCommittedURL(); | |
343 if (!url.is_valid()) | |
344 return web_contents->GetVisibleURL(); | |
345 return url; | |
346 } | |
347 | |
348 User* PlatformVerificationFlow::GetUser(content::WebContents* web_contents) { | |
349 if (!web_contents) | |
350 return user_manager_->GetActiveUser(); | |
351 return user_manager_->GetUserByProfile( | |
352 Profile::FromBrowserContext(web_contents->GetBrowserContext())); | |
353 } | |
354 | |
355 HostContentSettingsMap* PlatformVerificationFlow::GetContentSettings( | |
356 content::WebContents* web_contents) { | |
357 if (testing_content_settings_) | |
358 return testing_content_settings_; | |
359 return Profile::FromBrowserContext(web_contents->GetBrowserContext())-> | |
360 GetHostContentSettingsMap(); | |
361 } | |
362 | |
363 bool PlatformVerificationFlow::IsAttestationEnabled( | 355 bool PlatformVerificationFlow::IsAttestationEnabled( |
364 content::WebContents* web_contents) { | 356 content::WebContents* web_contents) { |
365 // Check the device policy for the feature. | 357 // Check the device policy for the feature. |
366 bool enabled_for_device = false; | 358 bool enabled_for_device = false; |
367 if (!CrosSettings::Get()->GetBoolean(kAttestationForContentProtectionEnabled, | 359 if (!CrosSettings::Get()->GetBoolean(kAttestationForContentProtectionEnabled, |
368 &enabled_for_device)) { | 360 &enabled_for_device)) { |
369 LOG(ERROR) << "Failed to get device setting."; | 361 LOG(ERROR) << "Failed to get device setting."; |
370 return false; | 362 return false; |
371 } | 363 } |
372 if (!enabled_for_device) | 364 if (!enabled_for_device) |
373 return false; | 365 return false; |
374 | 366 |
375 // Check the user preference for the feature. | 367 // Check the user preference for the feature. |
376 PrefService* pref_service = GetPrefs(web_contents); | 368 PrefService* pref_service = delegate_->GetPrefs(web_contents); |
377 if (!pref_service) { | 369 if (!pref_service) { |
378 LOG(ERROR) << "Failed to get user prefs."; | 370 LOG(ERROR) << "Failed to get user prefs."; |
379 return false; | 371 return false; |
380 } | 372 } |
381 if (!pref_service->GetBoolean(prefs::kEnableDRM)) | 373 if (!pref_service->GetBoolean(prefs::kEnableDRM)) |
382 return false; | 374 return false; |
383 | 375 |
384 // Check the user preference for this domain. | 376 // Check the user preference for this domain. |
385 bool enabled_for_domain = false; | 377 bool enabled_for_domain = false; |
386 bool found = GetDomainPref(GetContentSettings(web_contents), | 378 bool found = GetDomainPref(delegate_->GetContentSettings(web_contents), |
387 GetURL(web_contents), | 379 delegate_->GetURL(web_contents), |
388 &enabled_for_domain); | 380 &enabled_for_domain); |
389 return (!found || enabled_for_domain); | 381 return (!found || enabled_for_domain); |
390 } | 382 } |
391 | 383 |
392 bool PlatformVerificationFlow::UpdateSettings( | 384 bool PlatformVerificationFlow::UpdateSettings( |
393 content::WebContents* web_contents, | 385 content::WebContents* web_contents, |
394 ConsentResponse consent_response) { | 386 ConsentResponse consent_response) { |
395 PrefService* pref_service = GetPrefs(web_contents); | 387 PrefService* pref_service = delegate_->GetPrefs(web_contents); |
396 if (!pref_service) { | 388 if (!pref_service) { |
397 LOG(ERROR) << "Failed to get user prefs."; | 389 LOG(ERROR) << "Failed to get user prefs."; |
398 return false; | 390 return false; |
399 } | 391 } |
400 pref_service->SetBoolean(prefs::kRAConsentFirstTime, true); | 392 pref_service->SetBoolean(prefs::kRAConsentFirstTime, true); |
401 RecordDomainConsent(GetContentSettings(web_contents), | 393 RecordDomainConsent(delegate_->GetContentSettings(web_contents), |
402 GetURL(web_contents), | 394 delegate_->GetURL(web_contents), |
403 (consent_response == CONSENT_RESPONSE_ALLOW)); | 395 (consent_response == CONSENT_RESPONSE_ALLOW)); |
404 return true; | 396 return true; |
405 } | 397 } |
406 | 398 |
407 bool PlatformVerificationFlow::GetDomainPref( | 399 bool PlatformVerificationFlow::GetDomainPref( |
408 HostContentSettingsMap* content_settings, | 400 HostContentSettingsMap* content_settings, |
409 const GURL& url, | 401 const GURL& url, |
410 bool* pref_value) { | 402 bool* pref_value) { |
411 CHECK(content_settings); | 403 CHECK(content_settings); |
412 CHECK(url.is_valid()); | 404 CHECK(url.is_valid()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 scoped_refptr<net::X509Certificate> x509( | 452 scoped_refptr<net::X509Certificate> x509( |
461 net::X509Certificate::CreateFromBytes(certificate.data(), | 453 net::X509Certificate::CreateFromBytes(certificate.data(), |
462 certificate.length())); | 454 certificate.length())); |
463 if (!x509.get() || x509->valid_expiry().is_null()) { | 455 if (!x509.get() || x509->valid_expiry().is_null()) { |
464 LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; | 456 LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; |
465 return false; | 457 return false; |
466 } | 458 } |
467 return (base::Time::Now() > x509->valid_expiry()); | 459 return (base::Time::Now() > x509->valid_expiry()); |
468 } | 460 } |
469 | 461 |
470 bool PlatformVerificationFlow::IsGuestOrIncognito( | |
471 content::WebContents* web_contents) { | |
472 if (!web_contents) | |
473 return false; | |
474 Profile* profile = | |
475 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | |
476 return profile->IsOffTheRecord() || profile->IsGuestSession(); | |
477 } | |
478 | |
479 } // namespace attestation | 462 } // namespace attestation |
480 } // namespace chromeos | 463 } // namespace chromeos |
OLD | NEW |