OLD | NEW |
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_policy.h" | 5 #include "chrome/browser/ssl/ssl_policy.h" |
6 | 6 |
7 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
8 #include "app/resource_bundle.h" | 8 #include "app/resource_bundle.h" |
9 #include "base/base_switches.h" | 9 #include "base/base_switches.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 case net::ERR_CERT_INVALID: | 76 case net::ERR_CERT_INVALID: |
77 OnCertErrorInternal(handler, SSLBlockingPage::ERROR_FATAL); | 77 OnCertErrorInternal(handler, SSLBlockingPage::ERROR_FATAL); |
78 break; | 78 break; |
79 default: | 79 default: |
80 NOTREACHED(); | 80 NOTREACHED(); |
81 handler->CancelRequest(); | 81 handler->CancelRequest(); |
82 break; | 82 break; |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 void SSLPolicy::DidDisplayInsecureContent(NavigationEntry* entry) { | |
87 if (!entry) | |
88 return; | |
89 | |
90 // TODO(abarth): We don't actually need to break the whole origin here, | |
91 // but we can handle that in a later patch. | |
92 DidRunInsecureContent(entry, entry->url().spec()); | |
93 } | |
94 | |
95 void SSLPolicy::DidRunInsecureContent(NavigationEntry* entry, | 86 void SSLPolicy::DidRunInsecureContent(NavigationEntry* entry, |
96 const std::string& security_origin) { | 87 const std::string& security_origin) { |
97 if (!entry) | 88 if (!entry) |
98 return; | 89 return; |
99 | 90 |
100 SiteInstance* site_instance = entry->site_instance(); | 91 SiteInstance* site_instance = entry->site_instance(); |
101 if (!site_instance) | 92 if (!site_instance) |
102 return; | 93 return; |
103 | 94 |
104 backend_->MarkHostAsBroken(GURL(security_origin).host(), | 95 backend_->HostRanInsecureContent(GURL(security_origin).host(), |
105 site_instance->GetProcess()->id()); | 96 site_instance->GetProcess()->id()); |
106 } | 97 } |
107 | 98 |
108 void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) { | 99 void SSLPolicy::OnRequestStarted(SSLRequestInfo* info) { |
109 if (net::IsCertStatusError(info->ssl_cert_status())) | 100 // TODO(abarth): This mechanism is wrong. What we should be doing is sending |
110 UpdateStateForUnsafeContent(info); | 101 // this information back through WebKit and out some FrameLoaderClient |
| 102 // methods. |
| 103 // |
| 104 // The behavior for HTTPS resources with cert errors should be as follows: |
| 105 // 1) If we don't know anything about this host (the one hosting the |
| 106 // resource), the resource load just fails. |
| 107 // 2) If the user has previously approved the same certificate error for |
| 108 // this host in a full-page interstitial, then we'll proceed with the |
| 109 // load. |
| 110 // 3) If we proceed with the load, we should treat the resources as if they |
| 111 // were loaded over HTTP, w.r.t. the display vs. run distinction above. |
| 112 // |
| 113 // However, right now we don't have the proper context to understand where |
| 114 // these resources will be used. Consequently, we're conservative and treat |
| 115 // them all like DidRunInsecureContent(). |
| 116 |
| 117 if (net::IsCertStatusError(info->ssl_cert_status())) { |
| 118 backend_->HostRanInsecureContent(info->url().host(), info->child_id()); |
| 119 |
| 120 // TODO(abarth): We should eventually remove the main_frame_origin and |
| 121 // frame_origin properties. First, not every resource load is associated |
| 122 // with a frame, so they don't always make sense. Second, the |
| 123 // main_frame_origin is computed from the first_party_for_cookies, which has |
| 124 // been hacked to death to support third-party cookie blocking. |
| 125 |
| 126 if (info->resource_type() != ResourceType::MAIN_FRAME && |
| 127 info->resource_type() != ResourceType::SUB_FRAME) { |
| 128 // The frame's origin now contains mixed content and therefore is broken. |
| 129 OriginRanInsecureContent(info->frame_origin(), info->child_id()); |
| 130 } |
| 131 |
| 132 if (info->resource_type() != ResourceType::MAIN_FRAME) { |
| 133 // The main frame now contains a frame with mixed content. Therefore, we |
| 134 // mark the main frame's origin as broken too. |
| 135 OriginRanInsecureContent(info->main_frame_origin(), info->child_id()); |
| 136 } |
| 137 } |
111 } | 138 } |
112 | 139 |
113 void SSLPolicy::UpdateEntry(NavigationEntry* entry) { | 140 void SSLPolicy::UpdateEntry(NavigationEntry* entry, TabContents* tab_contents) { |
114 DCHECK(entry); | 141 DCHECK(entry); |
115 | 142 |
116 InitializeEntryIfNeeded(entry); | 143 InitializeEntryIfNeeded(entry); |
117 | 144 |
118 if (!entry->url().SchemeIsSecure()) | 145 if (!entry->url().SchemeIsSecure()) |
119 return; | 146 return; |
120 | 147 |
121 // An HTTPS response may not have a certificate for some reason. When that | 148 // An HTTPS response may not have a certificate for some reason. When that |
122 // happens, use the unauthenticated (HTTP) rather than the authentication | 149 // happens, use the unauthenticated (HTTP) rather than the authentication |
123 // broken security style so that we can detect this error condition. | 150 // broken security style so that we can detect this error condition. |
124 if (!entry->ssl().cert_id()) { | 151 if (!entry->ssl().cert_id()) { |
125 entry->ssl().set_security_style(SECURITY_STYLE_UNAUTHENTICATED); | 152 entry->ssl().set_security_style(SECURITY_STYLE_UNAUTHENTICATED); |
126 return; | 153 return; |
127 } | 154 } |
128 | 155 |
129 // If CERT_STATUS_UNABLE_TO_CHECK_REVOCATION is the only certificate error, | 156 // If CERT_STATUS_UNABLE_TO_CHECK_REVOCATION is the only certificate error, |
130 // don't lower the security style to SECURITY_STYLE_AUTHENTICATION_BROKEN. | 157 // don't lower the security style to SECURITY_STYLE_AUTHENTICATION_BROKEN. |
131 int cert_errors = entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS; | 158 int cert_errors = entry->ssl().cert_status() & net::CERT_STATUS_ALL_ERRORS; |
132 if (cert_errors) { | 159 if (cert_errors) { |
133 if (cert_errors != net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) | 160 if (cert_errors != net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION) |
134 entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN); | 161 entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN); |
135 return; | 162 return; |
136 } | 163 } |
137 | 164 |
138 SiteInstance* site_instance = entry->site_instance(); | 165 SiteInstance* site_instance = entry->site_instance(); |
139 // Note that |site_instance| can be NULL here because NavigationEntries don't | 166 // Note that |site_instance| can be NULL here because NavigationEntries don't |
140 // necessarily have site instances. Without a process, the entry can't | 167 // necessarily have site instances. Without a process, the entry can't |
141 // possibly have mixed content. See bug http://crbug.com/12423. | 168 // possibly have mixed content. See bug http://crbug.com/12423. |
142 if (site_instance && | 169 if (site_instance && |
143 backend_->DidMarkHostAsBroken(entry->url().host(), | 170 backend_->DidHostRunInsecureContent(entry->url().host(), |
144 site_instance->GetProcess()->id())) | 171 site_instance->GetProcess()->id())) { |
145 entry->ssl().set_has_mixed_content(); | 172 entry->ssl().set_security_style(SECURITY_STYLE_AUTHENTICATION_BROKEN); |
| 173 entry->ssl().set_ran_mixed_content(); |
| 174 return; |
| 175 } |
| 176 |
| 177 if (tab_contents->displayed_insecure_content()) |
| 178 entry->ssl().set_displayed_mixed_content(); |
146 } | 179 } |
147 | 180 |
148 //////////////////////////////////////////////////////////////////////////////// | 181 //////////////////////////////////////////////////////////////////////////////// |
149 // SSLBlockingPage::Delegate methods | 182 // SSLBlockingPage::Delegate methods |
150 | 183 |
151 SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLCertErrorHandler* handler) { | 184 SSLErrorInfo SSLPolicy::GetSSLErrorInfo(SSLCertErrorHandler* handler) { |
152 return SSLErrorInfo::CreateError( | 185 return SSLErrorInfo::CreateError( |
153 SSLErrorInfo::NetErrorToErrorType(handler->cert_error()), | 186 SSLErrorInfo::NetErrorToErrorType(handler->cert_error()), |
154 handler->ssl_info().cert, handler->request_url()); | 187 handler->ssl_info().cert, handler->request_url()); |
155 } | 188 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 } | 233 } |
201 | 234 |
202 void SSLPolicy::InitializeEntryIfNeeded(NavigationEntry* entry) { | 235 void SSLPolicy::InitializeEntryIfNeeded(NavigationEntry* entry) { |
203 if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN) | 236 if (entry->ssl().security_style() != SECURITY_STYLE_UNKNOWN) |
204 return; | 237 return; |
205 | 238 |
206 entry->ssl().set_security_style(entry->url().SchemeIsSecure() ? | 239 entry->ssl().set_security_style(entry->url().SchemeIsSecure() ? |
207 SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED); | 240 SECURITY_STYLE_AUTHENTICATED : SECURITY_STYLE_UNAUTHENTICATED); |
208 } | 241 } |
209 | 242 |
210 void SSLPolicy::MarkOriginAsBroken(const std::string& origin, int pid) { | 243 void SSLPolicy::OriginRanInsecureContent(const std::string& origin, int pid) { |
211 GURL parsed_origin(origin); | 244 GURL parsed_origin(origin); |
212 if (!parsed_origin.SchemeIsSecure()) | 245 if (parsed_origin.SchemeIsSecure()) |
213 return; | 246 backend_->HostRanInsecureContent(parsed_origin.host(), pid); |
214 | |
215 backend_->MarkHostAsBroken(parsed_origin.host(), pid); | |
216 } | 247 } |
217 | |
218 void SSLPolicy::UpdateStateForMixedContent(SSLRequestInfo* info) { | |
219 // TODO(abarth): This function isn't right because we need to remove | |
220 // info->main_frame_origin(). | |
221 | |
222 if (info->resource_type() != ResourceType::MAIN_FRAME && | |
223 info->resource_type() != ResourceType::SUB_FRAME) { | |
224 // The frame's origin now contains mixed content and therefore is broken. | |
225 MarkOriginAsBroken(info->frame_origin(), info->child_id()); | |
226 } | |
227 | |
228 if (info->resource_type() != ResourceType::MAIN_FRAME) { | |
229 // The main frame now contains a frame with mixed content. Therefore, we | |
230 // mark the main frame's origin as broken too. | |
231 MarkOriginAsBroken(info->main_frame_origin(), info->child_id()); | |
232 } | |
233 } | |
234 | |
235 void SSLPolicy::UpdateStateForUnsafeContent(SSLRequestInfo* info) { | |
236 // This request as a broken cert, which means its host is broken. | |
237 backend_->MarkHostAsBroken(info->url().host(), info->child_id()); | |
238 UpdateStateForMixedContent(info); | |
239 } | |
OLD | NEW |