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

Side by Side Diff: net/http/http_stream_factory_impl_job.cc

Issue 1074193003: Verify alternative server certificate validity for origin. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Verify certificate validity. Created 5 years, 8 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "net/http/http_stream_factory_impl_job.h" 5 #include "net/http/http_stream_factory_impl_job.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <string> 8 #include <string>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 // https://somehost/ that we don't use that session for http://somehost:443/. 285 // https://somehost/ that we don't use that session for http://somehost:443/.
286 // The only time we can use an existing session is if the request URL is 286 // The only time we can use an existing session is if the request URL is
287 // https (the normal case) or if we're connection to a SPDY proxy. 287 // https (the normal case) or if we're connection to a SPDY proxy.
288 // https://crbug.com/133176 288 // https://crbug.com/133176
289 // TODO(ricea): Add "wss" back to this list when SPDY WebSocket support is 289 // TODO(ricea): Add "wss" back to this list when SPDY WebSocket support is
290 // working. 290 // working.
291 return origin_url_.SchemeIs("https") || 291 return origin_url_.SchemeIs("https") ||
292 proxy_info_.proxy_server().is_https() || IsSpdyAlternate(); 292 proxy_info_.proxy_server().is_https() || IsSpdyAlternate();
293 } 293 }
294 294
295 bool HttpStreamFactoryImpl::Job::IsAlternativeCertificateValidForOrigin(
296 base::WeakPtr<SpdySession> spdy_session) {
297 DCHECK(spdy_session);
298 if (!using_ssl_) {
299 return true;
Ryan Hamilton 2015/04/10 18:37:37 We only speak SPDY over TLS, right? I think this c
Bence 2015/04/10 19:55:16 Well, not quite, this member was called for non-ss
300 }
301 if (origin_url_.host() == spdy_session->host_port_pair().host()) {
Ryan Hamilton 2015/04/10 18:37:36 It seems that this is simply a performance optimiz
Bence 2015/04/10 19:55:16 Not exactly. I added this test here because other
Ryan Hamilton 2015/04/11 02:40:41 Ah. I'm not a big fan of having "real" code that's
Bence 2015/04/13 17:52:40 I totally agree with you. It turns out that there
Ryan Hamilton 2015/04/13 18:29:56 It seems like it should be pretty easy to add a he
Bence 2015/04/15 21:07:46 Done.
302 return true;
303 }
304 return spdy_session->VerifyDomainAuthentication(origin_url_.host());
305 }
306
295 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() { 307 void HttpStreamFactoryImpl::Job::OnStreamReadyCallback() {
296 DCHECK(stream_.get()); 308 DCHECK(stream_.get());
297 DCHECK(!IsPreconnecting()); 309 DCHECK(!IsPreconnecting());
298 DCHECK(!stream_factory_->for_websockets_); 310 DCHECK(!stream_factory_->for_websockets_);
299 if (IsOrphaned()) { 311 if (IsOrphaned()) {
300 stream_factory_->OnOrphanedJobComplete(this); 312 stream_factory_->OnOrphanedJobComplete(this);
301 } else { 313 } else {
302 request_->Complete(was_npn_negotiated(), 314 request_->Complete(was_npn_negotiated(),
303 protocol_negotiated(), 315 protocol_negotiated(),
304 using_spdy(), 316 using_spdy(),
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 DCHECK(result == OK || waiting_job_ == NULL); 462 DCHECK(result == OK || waiting_job_ == NULL);
451 463
452 if (IsPreconnecting()) { 464 if (IsPreconnecting()) {
453 base::MessageLoop::current()->PostTask( 465 base::MessageLoop::current()->PostTask(
454 FROM_HERE, 466 FROM_HERE,
455 base::Bind(&HttpStreamFactoryImpl::Job::OnPreconnectsComplete, 467 base::Bind(&HttpStreamFactoryImpl::Job::OnPreconnectsComplete,
456 ptr_factory_.GetWeakPtr())); 468 ptr_factory_.GetWeakPtr()));
457 return ERR_IO_PENDING; 469 return ERR_IO_PENDING;
458 } 470 }
459 471
460 if (IsCertificateError(result)) { 472 if (IsCertificateError(result) &&
473 result != ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN) {
Ryan Hamilton 2015/04/10 18:37:37 Yeah, definitely move this error out of the certif
Bence 2015/04/10 19:55:16 Done.
461 // Retrieve SSL information from the socket. 474 // Retrieve SSL information from the socket.
462 GetSSLInfo(); 475 GetSSLInfo();
463 476
464 next_state_ = STATE_WAITING_USER_ACTION; 477 next_state_ = STATE_WAITING_USER_ACTION;
465 base::MessageLoop::current()->PostTask( 478 base::MessageLoop::current()->PostTask(
466 FROM_HERE, 479 FROM_HERE,
467 base::Bind(&HttpStreamFactoryImpl::Job::OnCertificateErrorCallback, 480 base::Bind(&HttpStreamFactoryImpl::Job::OnCertificateErrorCallback,
468 ptr_factory_.GetWeakPtr(), result, ssl_info_)); 481 ptr_factory_.GetWeakPtr(), result, ssl_info_));
469 return ERR_IO_PENDING; 482 return ERR_IO_PENDING;
470 } 483 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback, 541 base::Bind(&Job::OnWebSocketHandshakeStreamReadyCallback,
529 ptr_factory_.GetWeakPtr())); 542 ptr_factory_.GetWeakPtr()));
530 } else { 543 } else {
531 DCHECK(stream_.get()); 544 DCHECK(stream_.get());
532 base::MessageLoop::current()->PostTask( 545 base::MessageLoop::current()->PostTask(
533 FROM_HERE, 546 FROM_HERE,
534 base::Bind(&Job::OnStreamReadyCallback, ptr_factory_.GetWeakPtr())); 547 base::Bind(&Job::OnStreamReadyCallback, ptr_factory_.GetWeakPtr()));
535 } 548 }
536 return ERR_IO_PENDING; 549 return ERR_IO_PENDING;
537 550
551 case ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN:
Ryan Hamilton 2015/04/10 18:37:36 This should only happen for a job that IsAlternate
Bence 2015/04/10 19:55:16 This wasn't actually true, but yes, now it can onl
552 if (job_status_ != STATUS_BROKEN) {
553 DCHECK_EQ(STATUS_RUNNING, job_status_);
554 job_status_ = STATUS_FAILED;
555 // TODO(bnc): Instead of marking alternative service broken, mark
556 // (origin, alternative service) couple as invalid.
Ryan Hamilton 2015/04/10 18:37:37 Is this a TODO (instead of being implemented) beca
Bence 2015/04/10 19:55:16 Correct.
557 MaybeMarkAlternativeServiceBroken();
558 }
559 base::MessageLoop::current()->PostTask(
560 FROM_HERE,
561 base::Bind(&Job::OnStreamFailedCallback, ptr_factory_.GetWeakPtr(),
562 ERR_CONNECTION_REFUSED));
Ryan Hamilton 2015/04/10 18:37:37 Why ERR_CONNECTION_REFUSED? Actually, this looks a
Bence 2015/04/10 19:55:16 In fact, you are right, this is a lot like the def
Ryan Hamilton 2015/04/11 02:40:41 Is there a difference between the two cases? (defa
Bence 2015/04/13 17:52:40 Only the DCHECK (and the TODO), so I merged them f
563 return ERR_IO_PENDING;
564
538 default: 565 default:
539 if (job_status_ != STATUS_BROKEN) { 566 if (job_status_ != STATUS_BROKEN) {
540 DCHECK_EQ(STATUS_RUNNING, job_status_); 567 DCHECK_EQ(STATUS_RUNNING, job_status_);
541 job_status_ = STATUS_FAILED; 568 job_status_ = STATUS_FAILED;
542 MaybeMarkAlternativeServiceBroken(); 569 MaybeMarkAlternativeServiceBroken();
543 } 570 }
544 base::MessageLoop::current()->PostTask( 571 base::MessageLoop::current()->PostTask(
545 FROM_HERE, 572 FROM_HERE,
546 base::Bind(&Job::OnStreamFailedCallback, ptr_factory_.GetWeakPtr(), 573 base::Bind(&Job::OnStreamFailedCallback, ptr_factory_.GetWeakPtr(),
547 result)); 574 result));
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 return rv; 824 return rv;
798 } 825 }
799 826
800 // Check first if we have a spdy session for this group. If so, then go 827 // Check first if we have a spdy session for this group. If so, then go
801 // straight to using that. 828 // straight to using that.
802 SpdySessionKey spdy_session_key = GetSpdySessionKey(); 829 SpdySessionKey spdy_session_key = GetSpdySessionKey();
803 base::WeakPtr<SpdySession> spdy_session = 830 base::WeakPtr<SpdySession> spdy_session =
804 session_->spdy_session_pool()->FindAvailableSession( 831 session_->spdy_session_pool()->FindAvailableSession(
805 spdy_session_key, net_log_); 832 spdy_session_key, net_log_);
806 if (spdy_session && CanUseExistingSpdySession()) { 833 if (spdy_session && CanUseExistingSpdySession()) {
834 if (!IsAlternativeCertificateValidForOrigin(spdy_session)) {
Ryan Hamilton 2015/04/10 18:37:37 We don't need to do this call, unless this job is
Bence 2015/04/10 19:55:16 That is true. I think it might be easier to check
835 return ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN;
836 }
807 // If we're preconnecting, but we already have a SpdySession, we don't 837 // If we're preconnecting, but we already have a SpdySession, we don't
808 // actually need to preconnect any sockets, so we're done. 838 // actually need to preconnect any sockets, so we're done.
809 if (IsPreconnecting()) 839 if (IsPreconnecting())
810 return OK; 840 return OK;
811 using_spdy_ = true; 841 using_spdy_ = true;
812 next_state_ = STATE_CREATE_STREAM; 842 next_state_ = STATE_CREATE_STREAM;
813 existing_spdy_session_ = spdy_session; 843 existing_spdy_session_ = spdy_session;
814 return OK; 844 return OK;
815 } else if (request_ && !request_->HasSpdySessionKey() && using_ssl_) { 845 }
846 if (request_ && !request_->HasSpdySessionKey() && using_ssl_) {
816 // Update the spdy session key for the request that launched this job. 847 // Update the spdy session key for the request that launched this job.
817 request_->SetSpdySessionKey(spdy_session_key); 848 request_->SetSpdySessionKey(spdy_session_key);
818 } 849 }
819 850
820 // OK, there's no available SPDY session. Let |waiting_job_| resume if it's 851 // OK, there's no available SPDY session. Let |waiting_job_| resume if it's
821 // paused. 852 // paused.
822
823 if (waiting_job_) { 853 if (waiting_job_) {
824 waiting_job_->Resume(this); 854 waiting_job_->Resume(this);
825 waiting_job_ = NULL; 855 waiting_job_ = NULL;
826 } 856 }
827 857
828 if (proxy_info_.is_http() || proxy_info_.is_https()) 858 if (proxy_info_.is_http() || proxy_info_.is_https())
829 establishing_tunnel_ = using_ssl_; 859 establishing_tunnel_ = using_ssl_;
830 860
831 // TODO(bnc): s/want_spdy_over_npn/expect_spdy_over_npn/ 861 // TODO(bnc): s/want_spdy_over_npn/expect_spdy_over_npn/
832 bool want_spdy_over_npn = IsAlternate(); 862 bool want_spdy_over_npn = IsAlternate();
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 // puts the in progress HttpProxy socket into |connection_| in order to 1012 // puts the in progress HttpProxy socket into |connection_| in order to
983 // complete the auth (or read the response body). The tunnel restart code 1013 // complete the auth (or read the response body). The tunnel restart code
984 // is careful to remove it before returning control to the rest of this 1014 // is careful to remove it before returning control to the rest of this
985 // class. 1015 // class.
986 connection_.reset(connection_->release_pending_http_proxy_connection()); 1016 connection_.reset(connection_->release_pending_http_proxy_connection());
987 return result; 1017 return result;
988 } 1018 }
989 1019
990 if (!ssl_started && result < 0 && IsAlternate()) { 1020 if (!ssl_started && result < 0 && IsAlternate()) {
991 job_status_ = STATUS_BROKEN; 1021 job_status_ = STATUS_BROKEN;
1022 // TODO(bnc): if (result == ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN), then
1023 // instead of marking alternative service broken, mark (origin, alternative
1024 // service) couple as invalid.
992 MaybeMarkAlternativeServiceBroken(); 1025 MaybeMarkAlternativeServiceBroken();
993 return result; 1026 return result;
994 } 1027 }
995 1028
996 if (using_quic_) { 1029 if (using_quic_) {
997 if (result < 0) { 1030 if (result < 0) {
998 job_status_ = STATUS_BROKEN; 1031 job_status_ = STATUS_BROKEN;
999 MaybeMarkAlternativeServiceBroken(); 1032 MaybeMarkAlternativeServiceBroken();
1000 return result; 1033 return result;
1001 } 1034 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(), 1157 spdy_session_key = SpdySessionKey(proxy_server.host_port_pair(),
1125 ProxyServer::Direct(), 1158 ProxyServer::Direct(),
1126 PRIVACY_MODE_DISABLED); 1159 PRIVACY_MODE_DISABLED);
1127 } 1160 }
1128 1161
1129 SpdySessionPool* spdy_pool = session_->spdy_session_pool(); 1162 SpdySessionPool* spdy_pool = session_->spdy_session_pool();
1130 base::WeakPtr<SpdySession> spdy_session = 1163 base::WeakPtr<SpdySession> spdy_session =
1131 spdy_pool->FindAvailableSession(spdy_session_key, net_log_); 1164 spdy_pool->FindAvailableSession(spdy_session_key, net_log_);
1132 1165
1133 if (spdy_session) { 1166 if (spdy_session) {
1167 if (!IsAlternativeCertificateValidForOrigin(spdy_session)) {
1168 return ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN;
1169 }
1134 return SetSpdyHttpStream(spdy_session, direct); 1170 return SetSpdyHttpStream(spdy_session, direct);
1135 } 1171 }
1136 1172
1137 spdy_session = 1173 spdy_session =
1138 spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key, 1174 spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key,
1139 connection_.Pass(), 1175 connection_.Pass(),
1140 net_log_, 1176 net_log_,
1141 spdy_certificate_error_, 1177 spdy_certificate_error_,
1142 using_ssl_); 1178 using_ssl_);
1143 if (!spdy_session->HasAcceptableTransportSecurity()) { 1179 if (!spdy_session->HasAcceptableTransportSecurity()) {
1144 spdy_session->CloseSessionOnError( 1180 spdy_session->CloseSessionOnError(
1145 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, ""); 1181 ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY, "");
1146 return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY; 1182 return ERR_SPDY_INADEQUATE_TRANSPORT_SECURITY;
1147 } 1183 }
1148 1184
1185 if (!IsAlternativeCertificateValidForOrigin(spdy_session)) {
1186 return ERR_ALTERNATIVE_CERT_NOT_VALID_FOR_ORIGIN;
Ryan Hamilton 2015/04/10 18:37:37 Hm. It seems like there are a lot of different pla
Bence 2015/04/10 19:55:16 I do agree with you. Please let me know if you ha
Ryan Hamilton 2015/04/11 02:40:41 So it looks like each time we get a SPDY session f
Bence 2015/04/13 17:52:40 I've done it, but it doesn't quite feel right. Th
1187 }
1188
1149 new_spdy_session_ = spdy_session; 1189 new_spdy_session_ = spdy_session;
1150 spdy_session_direct_ = direct; 1190 spdy_session_direct_ = direct;
1151 const HostPortPair& host_port_pair = spdy_session_key.host_port_pair(); 1191 const HostPortPair& host_port_pair = spdy_session_key.host_port_pair();
1152 base::WeakPtr<HttpServerProperties> http_server_properties = 1192 base::WeakPtr<HttpServerProperties> http_server_properties =
1153 session_->http_server_properties(); 1193 session_->http_server_properties();
1154 if (http_server_properties) 1194 if (http_server_properties)
1155 http_server_properties->SetSupportsSpdy(host_port_pair, true); 1195 http_server_properties->SetSupportsSpdy(host_port_pair, true);
1156 1196
1157 // Create a SpdyHttpStream attached to the session; 1197 // Create a SpdyHttpStream attached to the session;
1158 // OnNewSpdySessionReadyCallback is not called until an event loop 1198 // OnNewSpdySessionReadyCallback is not called until an event loop
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 if (scheme == "https" || scheme == "wss" || IsSpdyAlternate()) 1521 if (scheme == "https" || scheme == "wss" || IsSpdyAlternate())
1482 return ClientSocketPoolManager::SSL_GROUP; 1522 return ClientSocketPoolManager::SSL_GROUP;
1483 1523
1484 if (scheme == "ftp") 1524 if (scheme == "ftp")
1485 return ClientSocketPoolManager::FTP_GROUP; 1525 return ClientSocketPoolManager::FTP_GROUP;
1486 1526
1487 return ClientSocketPoolManager::NORMAL_GROUP; 1527 return ClientSocketPoolManager::NORMAL_GROUP;
1488 } 1528 }
1489 1529
1490 } // namespace net 1530 } // namespace net
OLDNEW
« net/http/http_stream_factory_impl.cc ('K') | « net/http/http_stream_factory_impl_job.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698