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

Side by Side Diff: chrome/browser/ssl/ssl_manager.cc

Issue 2067003: Track "display" and "run" separately for mixed content, and make the latter d... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/ssl/ssl_manager.h" 5 #include "chrome/browser/ssl/ssl_manager.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "base/utf_string_conversions.h" 8 #include "base/utf_string_conversions.h"
9 #include "chrome/browser/chrome_thread.h" 9 #include "chrome/browser/chrome_thread.h"
10 #include "chrome/browser/load_from_memory_cache_details.h" 10 #include "chrome/browser/load_from_memory_cache_details.h"
(...skipping 10 matching lines...) Expand all
21 #include "chrome/common/pref_names.h" 21 #include "chrome/common/pref_names.h"
22 #include "grit/generated_resources.h" 22 #include "grit/generated_resources.h"
23 #include "net/base/cert_status_flags.h" 23 #include "net/base/cert_status_flags.h"
24 24
25 // static 25 // static
26 void SSLManager::RegisterUserPrefs(PrefService* prefs) { 26 void SSLManager::RegisterUserPrefs(PrefService* prefs) {
27 prefs->RegisterIntegerPref(prefs::kMixedContentFiltering, 27 prefs->RegisterIntegerPref(prefs::kMixedContentFiltering,
28 FilterPolicy::DONT_FILTER); 28 FilterPolicy::DONT_FILTER);
29 } 29 }
30 30
31 // static
32 void SSLManager::OnSSLCertificateError(ResourceDispatcherHost* rdh,
33 URLRequest* request,
34 int cert_error,
35 net::X509Certificate* cert) {
36 DLOG(INFO) << "OnSSLCertificateError() cert_error: " << cert_error <<
37 " url: " << request->url().spec();
38
39 ResourceDispatcherHostRequestInfo* info =
40 ResourceDispatcherHost::InfoForRequest(request);
41 DCHECK(info);
42
43 // A certificate error occurred. Construct a SSLCertErrorHandler object and
44 // hand it over to the UI thread for processing.
45 ChromeThread::PostTask(
46 ChromeThread::UI, FROM_HERE,
47 NewRunnableMethod(new SSLCertErrorHandler(rdh,
48 request,
49 info->resource_type(),
50 info->frame_origin(),
51 info->main_frame_origin(),
52 cert_error,
53 cert),
54 &SSLCertErrorHandler::Dispatch));
55 }
56
57 // static
58 void SSLManager::NotifySSLInternalStateChanged() {
59 NotificationService::current()->Notify(
60 NotificationType::SSL_INTERNAL_STATE_CHANGED,
61 NotificationService::AllSources(),
62 NotificationService::NoDetails());
63 }
64
65 // static
66 std::string SSLManager::SerializeSecurityInfo(int cert_id,
67 int cert_status,
68 int security_bits) {
69 Pickle pickle;
70 pickle.WriteInt(cert_id);
71 pickle.WriteInt(cert_status);
72 pickle.WriteInt(security_bits);
73 return std::string(static_cast<const char*>(pickle.data()), pickle.size());
74 }
75
76 // static
77 bool SSLManager::DeserializeSecurityInfo(const std::string& state,
78 int* cert_id,
79 int* cert_status,
80 int* security_bits) {
81 DCHECK(cert_id && cert_status && security_bits);
82 if (state.empty()) {
83 // No SSL used.
84 *cert_id = 0;
85 *cert_status = 0;
86 *security_bits = -1;
87 return false;
88 }
89
90 Pickle pickle(state.data(), static_cast<int>(state.size()));
91 void * iter = NULL;
92 return pickle.ReadInt(&iter, cert_id) &&
93 pickle.ReadInt(&iter, cert_status) &&
94 pickle.ReadInt(&iter, security_bits);
95 }
96
97 // static
98 std::wstring SSLManager::GetEVCertName(const net::X509Certificate& cert) {
99 // EV are required to have an organization name and country.
100 if (cert.subject().organization_names.empty() ||
101 cert.subject().country_name.empty()) {
102 NOTREACHED();
103 return std::wstring();
104 }
105
106 return l10n_util::GetStringF(IDS_SECURE_CONNECTION_EV,
107 UTF8ToWide(cert.subject().organization_names[0]),
108 UTF8ToWide(cert.subject().country_name));
109 }
110
31 SSLManager::SSLManager(NavigationController* controller) 111 SSLManager::SSLManager(NavigationController* controller)
32 : backend_(controller), 112 : backend_(controller),
33 policy_(new SSLPolicy(&backend_)), 113 policy_(new SSLPolicy(&backend_)),
34 controller_(controller) { 114 controller_(controller) {
35 DCHECK(controller_); 115 DCHECK(controller_);
36 116
37 // Subscribe to various notifications. 117 // Subscribe to various notifications.
38 registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR, 118 registrar_.Add(this, NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR,
39 Source<NavigationController>(controller_)); 119 Source<NavigationController>(controller_));
40 registrar_.Add(this, NotificationType::RESOURCE_RESPONSE_STARTED, 120 registrar_.Add(this, NotificationType::RESOURCE_RESPONSE_STARTED,
41 Source<NavigationController>(controller_)); 121 Source<NavigationController>(controller_));
42 registrar_.Add(this, NotificationType::RESOURCE_RECEIVED_REDIRECT, 122 registrar_.Add(this, NotificationType::RESOURCE_RECEIVED_REDIRECT,
43 Source<NavigationController>(controller_)); 123 Source<NavigationController>(controller_));
44 registrar_.Add(this, NotificationType::LOAD_FROM_MEMORY_CACHE, 124 registrar_.Add(this, NotificationType::LOAD_FROM_MEMORY_CACHE,
45 Source<NavigationController>(controller_)); 125 Source<NavigationController>(controller_));
46 registrar_.Add(this, NotificationType::SSL_INTERNAL_STATE_CHANGED, 126 registrar_.Add(this, NotificationType::SSL_INTERNAL_STATE_CHANGED,
47 NotificationService::AllSources()); 127 NotificationService::AllSources());
48 } 128 }
49 129
50 SSLManager::~SSLManager() { 130 SSLManager::~SSLManager() {
51 } 131 }
52 132
133 void SSLManager::DidCommitProvisionalLoad(
134 const NotificationDetails& in_details) {
135 NavigationController::LoadCommittedDetails* details =
136 Details<NavigationController::LoadCommittedDetails>(in_details).ptr();
137
138 NavigationEntry* entry = controller_->GetActiveEntry();
139
140 if (details->is_main_frame) {
141 if (entry) {
142 // Decode the security details.
143 int ssl_cert_id, ssl_cert_status, ssl_security_bits;
144 DeserializeSecurityInfo(details->serialized_security_info,
145 &ssl_cert_id,
146 &ssl_cert_status,
147 &ssl_security_bits);
148
149 // We may not have an entry if this is a navigation to an initial blank
150 // page. Reset the SSL information and add the new data we have.
151 entry->ssl() = NavigationEntry::SSLStatus();
152 entry->ssl().set_cert_id(ssl_cert_id);
153 entry->ssl().set_cert_status(ssl_cert_status);
154 entry->ssl().set_security_bits(ssl_security_bits);
155 }
156 backend_.ShowPendingMessages();
157 }
158
159 UpdateEntry(entry);
160 }
161
162 void SSLManager::DidRunInsecureContent(const std::string& security_origin) {
163 policy()->DidRunInsecureContent(controller_->GetActiveEntry(),
164 security_origin);
165 }
166
53 bool SSLManager::ProcessedSSLErrorFromRequest() const { 167 bool SSLManager::ProcessedSSLErrorFromRequest() const {
54 NavigationEntry* entry = controller_->GetActiveEntry(); 168 NavigationEntry* entry = controller_->GetActiveEntry();
55 if (!entry) { 169 if (!entry) {
56 NOTREACHED(); 170 NOTREACHED();
57 return false; 171 return false;
58 } 172 }
59 173
60 return net::IsCertStatusError(entry->ssl().cert_status()); 174 return net::IsCertStatusError(entry->ssl().cert_status());
61 } 175 }
62 176
63 // static
64 void SSLManager::OnSSLCertificateError(ResourceDispatcherHost* rdh,
65 URLRequest* request,
66 int cert_error,
67 net::X509Certificate* cert) {
68 DLOG(INFO) << "OnSSLCertificateError() cert_error: " << cert_error <<
69 " url: " << request->url().spec();
70
71 ResourceDispatcherHostRequestInfo* info =
72 ResourceDispatcherHost::InfoForRequest(request);
73 DCHECK(info);
74
75 // A certificate error occurred. Construct a SSLCertErrorHandler object and
76 // hand it over to the UI thread for processing.
77 ChromeThread::PostTask(
78 ChromeThread::UI, FROM_HERE,
79 NewRunnableMethod(new SSLCertErrorHandler(rdh,
80 request,
81 info->resource_type(),
82 info->frame_origin(),
83 info->main_frame_origin(),
84 cert_error,
85 cert),
86 &SSLCertErrorHandler::Dispatch));
87 }
88
89 void SSLManager::DidDisplayInsecureContent() {
90 policy()->DidDisplayInsecureContent(controller_->GetActiveEntry());
91 }
92
93 void SSLManager::DidRunInsecureContent(const std::string& security_origin) {
94 policy()->DidRunInsecureContent(controller_->GetActiveEntry(),
95 security_origin);
96 }
97
98 void SSLManager::Observe(NotificationType type, 177 void SSLManager::Observe(NotificationType type,
99 const NotificationSource& source, 178 const NotificationSource& source,
100 const NotificationDetails& details) { 179 const NotificationDetails& details) {
101 // Dispatch by type. 180 // Dispatch by type.
102 switch (type.value) { 181 switch (type.value) {
103 case NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR: 182 case NotificationType::FAIL_PROVISIONAL_LOAD_WITH_ERROR:
104 DidFailProvisionalLoadWithError( 183 DidFailProvisionalLoadWithError(
105 Details<ProvisionalLoadDetails>(details).ptr()); 184 Details<ProvisionalLoadDetails>(details).ptr());
106 break; 185 break;
107 case NotificationType::RESOURCE_RESPONSE_STARTED: 186 case NotificationType::RESOURCE_RESPONSE_STARTED:
108 DidStartResourceResponse(Details<ResourceRequestDetails>(details).ptr()); 187 DidStartResourceResponse(Details<ResourceRequestDetails>(details).ptr());
109 break; 188 break;
110 case NotificationType::RESOURCE_RECEIVED_REDIRECT: 189 case NotificationType::RESOURCE_RECEIVED_REDIRECT:
111 DidReceiveResourceRedirect( 190 DidReceiveResourceRedirect(
112 Details<ResourceRedirectDetails>(details).ptr()); 191 Details<ResourceRedirectDetails>(details).ptr());
113 break; 192 break;
114 case NotificationType::LOAD_FROM_MEMORY_CACHE: 193 case NotificationType::LOAD_FROM_MEMORY_CACHE:
115 DidLoadFromMemoryCache( 194 DidLoadFromMemoryCache(
116 Details<LoadFromMemoryCacheDetails>(details).ptr()); 195 Details<LoadFromMemoryCacheDetails>(details).ptr());
117 break; 196 break;
118 case NotificationType::SSL_INTERNAL_STATE_CHANGED: 197 case NotificationType::SSL_INTERNAL_STATE_CHANGED:
119 DidChangeSSLInternalState(); 198 DidChangeSSLInternalState();
120 break; 199 break;
121 default: 200 default:
122 NOTREACHED() << "The SSLManager received an unexpected notification."; 201 NOTREACHED() << "The SSLManager received an unexpected notification.";
123 } 202 }
124 } 203 }
125 204
126 void SSLManager::DispatchSSLVisibleStateChanged() {
127 NotificationService::current()->Notify(
128 NotificationType::SSL_VISIBLE_STATE_CHANGED,
129 Source<NavigationController>(controller_),
130 NotificationService::NoDetails());
131 }
132
133 void SSLManager::UpdateEntry(NavigationEntry* entry) {
134 // We don't always have a navigation entry to update, for example in the
135 // case of the Web Inspector.
136 if (!entry)
137 return;
138
139 NavigationEntry::SSLStatus original_ssl_status = entry->ssl(); // Copy!
140
141 policy()->UpdateEntry(entry);
142
143 if (!entry->ssl().Equals(original_ssl_status))
144 DispatchSSLVisibleStateChanged();
145 }
146
147 void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) { 205 void SSLManager::DidLoadFromMemoryCache(LoadFromMemoryCacheDetails* details) {
148 DCHECK(details); 206 DCHECK(details);
149 207
150 // Simulate loading this resource through the usual path. 208 // Simulate loading this resource through the usual path.
151 // Note that we specify SUB_RESOURCE as the resource type as WebCore only 209 // Note that we specify SUB_RESOURCE as the resource type as WebCore only
152 // caches sub-resources. 210 // caches sub-resources.
153 // This resource must have been loaded with FilterPolicy::DONT_FILTER because 211 // This resource must have been loaded with FilterPolicy::DONT_FILTER because
154 // filtered resouces aren't cachable. 212 // filtered resouces aren't cachable.
155 scoped_refptr<SSLRequestInfo> info = new SSLRequestInfo( 213 scoped_refptr<SSLRequestInfo> info = new SSLRequestInfo(
156 details->url(), 214 details->url(),
157 ResourceType::SUB_RESOURCE, 215 ResourceType::SUB_RESOURCE,
158 details->frame_origin(), 216 details->frame_origin(),
159 details->main_frame_origin(), 217 details->main_frame_origin(),
160 FilterPolicy::DONT_FILTER, 218 FilterPolicy::DONT_FILTER,
161 details->pid(), 219 details->pid(),
162 details->ssl_cert_id(), 220 details->ssl_cert_id(),
163 details->ssl_cert_status()); 221 details->ssl_cert_status());
164 222
165 // Simulate loading this resource through the usual path. 223 // Simulate loading this resource through the usual path.
166 policy()->OnRequestStarted(info.get()); 224 policy()->OnRequestStarted(info.get());
167 } 225 }
168 226
169 void SSLManager::DidCommitProvisionalLoad(
170 const NotificationDetails& in_details) {
171 NavigationController::LoadCommittedDetails* details =
172 Details<NavigationController::LoadCommittedDetails>(in_details).ptr();
173
174 NavigationEntry* entry = controller_->GetActiveEntry();
175
176 if (details->is_main_frame) {
177 if (entry) {
178 // Decode the security details.
179 int ssl_cert_id, ssl_cert_status, ssl_security_bits;
180 DeserializeSecurityInfo(details->serialized_security_info,
181 &ssl_cert_id,
182 &ssl_cert_status,
183 &ssl_security_bits);
184
185 // We may not have an entry if this is a navigation to an initial blank
186 // page. Reset the SSL information and add the new data we have.
187 entry->ssl() = NavigationEntry::SSLStatus();
188 entry->ssl().set_cert_id(ssl_cert_id);
189 entry->ssl().set_cert_status(ssl_cert_status);
190 entry->ssl().set_security_bits(ssl_security_bits);
191 }
192 backend_.ShowPendingMessages();
193 }
194
195 UpdateEntry(entry);
196 }
197
198 void SSLManager::DidFailProvisionalLoadWithError( 227 void SSLManager::DidFailProvisionalLoadWithError(
199 ProvisionalLoadDetails* details) { 228 ProvisionalLoadDetails* details) {
200 DCHECK(details); 229 DCHECK(details);
201 230
202 // Ignore in-page navigations. 231 // Ignore in-page navigations.
203 if (details->in_page_navigation()) 232 if (details->in_page_navigation())
204 return; 233 return;
205 234
206 if (details->main_frame()) 235 if (details->main_frame())
207 backend_.ClearPendingMessages(); 236 backend_.ClearPendingMessages();
(...skipping 23 matching lines...) Expand all
231 // a non-HTTPS resource in the redirect chain, we want to 260 // a non-HTTPS resource in the redirect chain, we want to
232 // trigger mixed content, even if the redirect chain goes back 261 // trigger mixed content, even if the redirect chain goes back
233 // to HTTPS. This is because the network attacker can redirect 262 // to HTTPS. This is because the network attacker can redirect
234 // the HTTP request to https://attacker.com/payload.js. 263 // the HTTP request to https://attacker.com/payload.js.
235 } 264 }
236 265
237 void SSLManager::DidChangeSSLInternalState() { 266 void SSLManager::DidChangeSSLInternalState() {
238 UpdateEntry(controller_->GetActiveEntry()); 267 UpdateEntry(controller_->GetActiveEntry());
239 } 268 }
240 269
241 // static 270 void SSLManager::UpdateEntry(NavigationEntry* entry) {
242 std::string SSLManager::SerializeSecurityInfo(int cert_id, 271 // We don't always have a navigation entry to update, for example in the
243 int cert_status, 272 // case of the Web Inspector.
244 int security_bits) { 273 if (!entry)
245 Pickle pickle; 274 return;
246 pickle.WriteInt(cert_id); 275
247 pickle.WriteInt(cert_status); 276 NavigationEntry::SSLStatus original_ssl_status = entry->ssl(); // Copy!
248 pickle.WriteInt(security_bits); 277
249 return std::string(static_cast<const char*>(pickle.data()), pickle.size()); 278 policy()->UpdateEntry(entry, controller_->tab_contents());
279
280 if (!entry->ssl().Equals(original_ssl_status)) {
281 NotificationService::current()->Notify(
282 NotificationType::SSL_VISIBLE_STATE_CHANGED,
283 Source<NavigationController>(controller_),
284 NotificationService::NoDetails());
285 }
250 } 286 }
251
252 // static
253 bool SSLManager::DeserializeSecurityInfo(const std::string& state,
254 int* cert_id,
255 int* cert_status,
256 int* security_bits) {
257 DCHECK(cert_id && cert_status && security_bits);
258 if (state.empty()) {
259 // No SSL used.
260 *cert_id = 0;
261 *cert_status = 0;
262 *security_bits = -1;
263 return false;
264 }
265
266 Pickle pickle(state.data(), static_cast<int>(state.size()));
267 void * iter = NULL;
268 return pickle.ReadInt(&iter, cert_id) &&
269 pickle.ReadInt(&iter, cert_status) &&
270 pickle.ReadInt(&iter, security_bits);
271 }
272
273 // static
274 std::wstring SSLManager::GetEVCertName(const net::X509Certificate& cert) {
275 // EV are required to have an organization name and country.
276 if (cert.subject().organization_names.empty() ||
277 cert.subject().country_name.empty()) {
278 NOTREACHED();
279 return std::wstring();
280 }
281
282 return l10n_util::GetStringF(IDS_SECURE_CONNECTION_EV,
283 UTF8ToWide(cert.subject().organization_names[0]),
284 UTF8ToWide(cert.subject().country_name));
285 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698