| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 #import "components/cronet/ios/Cronet.h" | 5 #import "components/cronet/ios/Cronet.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 class CronetHttpProtocolHandlerDelegate; | 27 class CronetHttpProtocolHandlerDelegate; |
| 28 | 28 |
| 29 using QuicHintVector = | 29 using QuicHintVector = |
| 30 std::vector<std::unique_ptr<cronet::URLRequestContextConfig::QuicHint>>; | 30 std::vector<std::unique_ptr<cronet::URLRequestContextConfig::QuicHint>>; |
| 31 // Currently there is one and only one instance of CronetEnvironment, | 31 // Currently there is one and only one instance of CronetEnvironment, |
| 32 // which is leaked at the shutdown. We should consider allowing multiple | 32 // which is leaked at the shutdown. We should consider allowing multiple |
| 33 // instances if that makes sense in the future. | 33 // instances if that makes sense in the future. |
| 34 base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky | 34 base::LazyInstance<std::unique_ptr<cronet::CronetEnvironment>>::Leaky |
| 35 gChromeNet = LAZY_INSTANCE_INITIALIZER; | 35 gChromeNet = LAZY_INSTANCE_INITIALIZER; |
| 36 | 36 |
| 37 // TODO(lilyhoughton) make these independent across Cronet instances, i.e.: |
| 38 // refresh them on shutdown, and add tests to make sure the defaults are |
| 39 // sane. |
| 37 BOOL gHttp2Enabled = YES; | 40 BOOL gHttp2Enabled = YES; |
| 38 BOOL gQuicEnabled = NO; | 41 BOOL gQuicEnabled = NO; |
| 39 cronet::URLRequestContextConfig::HttpCacheType gHttpCache = | 42 cronet::URLRequestContextConfig::HttpCacheType gHttpCache = |
| 40 cronet::URLRequestContextConfig::HttpCacheType::DISK; | 43 cronet::URLRequestContextConfig::HttpCacheType::DISK; |
| 41 QuicHintVector gQuicHints; | 44 QuicHintVector gQuicHints; |
| 42 NSString* gExperimentalOptions = @"{}"; | 45 NSString* gExperimentalOptions = @"{}"; |
| 43 NSString* gUserAgent = nil; | 46 NSString* gUserAgent = nil; |
| 44 BOOL gUserAgentPartial = NO; | 47 BOOL gUserAgentPartial = NO; |
| 45 NSString* gSslKeyLogFileName = nil; | 48 NSString* gSslKeyLogFileName = nil; |
| 46 std::vector<std::unique_ptr<cronet::URLRequestContextConfig::Pkp>> gPkpList; | 49 std::vector<std::unique_ptr<cronet::URLRequestContextConfig::Pkp>> gPkpList; |
| 47 RequestFilterBlock gRequestFilterBlock = nil; | 50 RequestFilterBlock gRequestFilterBlock = nil; |
| 48 base::LazyInstance<std::unique_ptr<CronetHttpProtocolHandlerDelegate>>::Leaky | 51 base::LazyInstance<std::unique_ptr<CronetHttpProtocolHandlerDelegate>>::Leaky |
| 49 gHttpProtocolHandlerDelegate = LAZY_INSTANCE_INITIALIZER; | 52 gHttpProtocolHandlerDelegate = LAZY_INSTANCE_INITIALIZER; |
| 50 NSURLCache* gPreservedSharedURLCache = nil; | 53 NSURLCache* gPreservedSharedURLCache = nil; |
| 51 BOOL gEnableTestCertVerifierForTesting = FALSE; | 54 BOOL gEnableTestCertVerifierForTesting = NO; |
| 52 std::unique_ptr<net::CertVerifier> gMockCertVerifier; | 55 std::unique_ptr<net::CertVerifier> gMockCertVerifier; |
| 53 NSString* gAcceptLanguages = nil; | 56 NSString* gAcceptLanguages = nil; |
| 57 BOOL gEnablePKPBypassForLocalTrustAnchors = YES; |
| 54 | 58 |
| 55 // CertVerifier, which allows any certificates for testing. | 59 // CertVerifier, which allows any certificates for testing. |
| 56 class TestCertVerifier : public net::CertVerifier { | 60 class TestCertVerifier : public net::CertVerifier { |
| 57 int Verify(const RequestParams& params, | 61 int Verify(const RequestParams& params, |
| 58 net::CRLSet* crl_set, | 62 net::CRLSet* crl_set, |
| 59 net::CertVerifyResult* verify_result, | 63 net::CertVerifyResult* verify_result, |
| 60 const net::CompletionCallback& callback, | 64 const net::CompletionCallback& callback, |
| 61 std::unique_ptr<Request>* out_req, | 65 std::unique_ptr<Request>* out_req, |
| 62 const net::NetLogWithSource& net_log) override { | 66 const net::NetLogWithSource& net_log) override { |
| 63 net::Error result = net::OK; | 67 net::Error result = net::OK; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 gRequestFilterBlock = block; | 222 gRequestFilterBlock = block; |
| 219 } | 223 } |
| 220 | 224 |
| 221 + (BOOL)addPublicKeyPinsForHost:(NSString*)host | 225 + (BOOL)addPublicKeyPinsForHost:(NSString*)host |
| 222 pinHashes:(NSSet<NSData*>*)pinHashes | 226 pinHashes:(NSSet<NSData*>*)pinHashes |
| 223 includeSubdomains:(BOOL)includeSubdomains | 227 includeSubdomains:(BOOL)includeSubdomains |
| 224 expirationDate:(NSDate*)expirationDate | 228 expirationDate:(NSDate*)expirationDate |
| 225 error:(NSError**)outError { | 229 error:(NSError**)outError { |
| 226 [self checkNotStarted]; | 230 [self checkNotStarted]; |
| 227 | 231 |
| 232 // Pinning a key only makes sense if pin bypassing has been disabled |
| 233 if (gEnablePKPBypassForLocalTrustAnchors) { |
| 234 *outError = |
| 235 [self createUnsupportedConfigurationError: |
| 236 @"Cannot pin keys while public key pinning is bypassed"]; |
| 237 return NO; |
| 238 } |
| 239 |
| 228 auto pkp = base::MakeUnique<cronet::URLRequestContextConfig::Pkp>( | 240 auto pkp = base::MakeUnique<cronet::URLRequestContextConfig::Pkp>( |
| 229 base::SysNSStringToUTF8(host), includeSubdomains, | 241 base::SysNSStringToUTF8(host), includeSubdomains, |
| 230 base::Time::FromCFAbsoluteTime( | 242 base::Time::FromCFAbsoluteTime( |
| 231 [expirationDate timeIntervalSinceReferenceDate])); | 243 [expirationDate timeIntervalSinceReferenceDate])); |
| 232 | 244 |
| 233 for (NSData* hash in pinHashes) { | 245 for (NSData* hash in pinHashes) { |
| 234 net::SHA256HashValue hashValue = net::SHA256HashValue(); | 246 net::SHA256HashValue hashValue = net::SHA256HashValue(); |
| 235 if (sizeof(hashValue.data) != hash.length) { | 247 if (sizeof(hashValue.data) != hash.length) { |
| 236 *outError = | 248 *outError = |
| 237 [self createIllegalArgumentErrorWithArgument:@"pinHashes" | 249 [self createIllegalArgumentErrorWithArgument:@"pinHashes" |
| 238 reason: | 250 reason: |
| 239 @"The length of PKP SHA256 " | 251 @"The length of PKP SHA256 " |
| 240 @"hash should be 256 bits"]; | 252 @"hash should be 256 bits"]; |
| 241 return NO; | 253 return NO; |
| 242 } | 254 } |
| 243 memcpy((void*)(hashValue.data), [hash bytes], sizeof(hashValue.data)); | 255 memcpy((void*)(hashValue.data), [hash bytes], sizeof(hashValue.data)); |
| 244 pkp->pin_hashes.push_back(net::HashValue(hashValue)); | 256 pkp->pin_hashes.push_back(net::HashValue(hashValue)); |
| 245 } | 257 } |
| 246 gPkpList.push_back(std::move(pkp)); | 258 gPkpList.push_back(std::move(pkp)); |
| 247 if (outError) { | 259 if (outError) { |
| 248 *outError = nil; | 260 *outError = nil; |
| 249 } | 261 } |
| 250 return YES; | 262 return YES; |
| 251 } | 263 } |
| 252 | 264 |
| 265 + (void)setEnablePublicKeyPinningBypassForLocalTrustAnchors:(BOOL)enable { |
| 266 gEnablePKPBypassForLocalTrustAnchors = enable; |
| 267 } |
| 268 |
| 253 + (void)startInternal { | 269 + (void)startInternal { |
| 254 std::string user_agent = base::SysNSStringToUTF8(gUserAgent); | 270 std::string user_agent = base::SysNSStringToUTF8(gUserAgent); |
| 255 | 271 |
| 256 gChromeNet.Get().reset( | 272 gChromeNet.Get().reset( |
| 257 new cronet::CronetEnvironment(user_agent, gUserAgentPartial)); | 273 new cronet::CronetEnvironment(user_agent, gUserAgentPartial)); |
| 258 | 274 |
| 259 gChromeNet.Get()->set_accept_language( | 275 gChromeNet.Get()->set_accept_language( |
| 260 base::SysNSStringToUTF8(gAcceptLanguages ?: [self getAcceptLanguages])); | 276 base::SysNSStringToUTF8(gAcceptLanguages ?: [self getAcceptLanguages])); |
| 261 | 277 |
| 262 gChromeNet.Get()->set_http2_enabled(gHttp2Enabled); | 278 gChromeNet.Get()->set_http2_enabled(gHttp2Enabled); |
| 263 gChromeNet.Get()->set_quic_enabled(gQuicEnabled); | 279 gChromeNet.Get()->set_quic_enabled(gQuicEnabled); |
| 264 gChromeNet.Get()->set_experimental_options( | 280 gChromeNet.Get()->set_experimental_options( |
| 265 base::SysNSStringToUTF8(gExperimentalOptions)); | 281 base::SysNSStringToUTF8(gExperimentalOptions)); |
| 266 gChromeNet.Get()->set_http_cache(gHttpCache); | 282 gChromeNet.Get()->set_http_cache(gHttpCache); |
| 267 gChromeNet.Get()->set_ssl_key_log_file_name( | 283 gChromeNet.Get()->set_ssl_key_log_file_name( |
| 268 base::SysNSStringToUTF8(gSslKeyLogFileName)); | 284 base::SysNSStringToUTF8(gSslKeyLogFileName)); |
| 269 gChromeNet.Get()->set_pkp_list(std::move(gPkpList)); | 285 gChromeNet.Get()->set_pkp_list(std::move(gPkpList)); |
| 286 gChromeNet.Get() |
| 287 ->set_enable_public_key_pinning_bypass_for_local_trust_anchors( |
| 288 gEnablePKPBypassForLocalTrustAnchors); |
| 270 for (const auto& quicHint : gQuicHints) { | 289 for (const auto& quicHint : gQuicHints) { |
| 271 gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port, | 290 gChromeNet.Get()->AddQuicHint(quicHint->host, quicHint->port, |
| 272 quicHint->alternate_port); | 291 quicHint->alternate_port); |
| 273 } | 292 } |
| 274 | 293 |
| 275 [self configureCronetEnvironmentForTesting:gChromeNet.Get().get()]; | 294 [self configureCronetEnvironmentForTesting:gChromeNet.Get().get()]; |
| 276 gChromeNet.Get()->Start(); | 295 gChromeNet.Get()->Start(); |
| 277 gHttpProtocolHandlerDelegate.Get().reset( | 296 gHttpProtocolHandlerDelegate.Get().reset( |
| 278 new CronetHttpProtocolHandlerDelegate( | 297 new CronetHttpProtocolHandlerDelegate( |
| 279 gChromeNet.Get()->GetURLRequestContextGetter(), gRequestFilterBlock)); | 298 gChromeNet.Get()->GetURLRequestContextGetter(), gRequestFilterBlock)); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 reason:(NSString*)reason { | 420 reason:(NSString*)reason { |
| 402 NSMutableDictionary* errorDictionary = | 421 NSMutableDictionary* errorDictionary = |
| 403 [[NSMutableDictionary alloc] initWithDictionary:@{ | 422 [[NSMutableDictionary alloc] initWithDictionary:@{ |
| 404 NSLocalizedDescriptionKey : | 423 NSLocalizedDescriptionKey : |
| 405 [NSString stringWithFormat:@"Invalid argument: %@", argumentName], | 424 [NSString stringWithFormat:@"Invalid argument: %@", argumentName], |
| 406 CRNInvalidArgumentKey : argumentName | 425 CRNInvalidArgumentKey : argumentName |
| 407 }]; | 426 }]; |
| 408 if (reason) { | 427 if (reason) { |
| 409 errorDictionary[NSLocalizedFailureReasonErrorKey] = reason; | 428 errorDictionary[NSLocalizedFailureReasonErrorKey] = reason; |
| 410 } | 429 } |
| 411 return [self createCronetErrorWith:CRNErrorInvalidArgument | 430 return [self createCronetErrorWithCode:CRNErrorInvalidArgument |
| 412 userInfo:errorDictionary]; | 431 userInfo:errorDictionary]; |
| 413 } | 432 } |
| 414 | 433 |
| 415 + (NSError*)createCronetErrorWith:(int)errorCode | 434 + (NSError*)createUnsupportedConfigurationError:(NSString*)contradiction { |
| 416 userInfo:(NSDictionary*)userInfo { | 435 NSMutableDictionary* errorDictionary = |
| 436 [[NSMutableDictionary alloc] initWithDictionary:@{ |
| 437 NSLocalizedDescriptionKey : @"Unsupported configuration", |
| 438 NSLocalizedRecoverySuggestionErrorKey : |
| 439 @"Try disabling Public Key Pinning Bypass before pinning keys.", |
| 440 NSLocalizedFailureReasonErrorKey : @"Pinning public keys while local " |
| 441 @"anchor bypass is enabled is " |
| 442 @"currently not supported.", |
| 443 }]; |
| 444 if (contradiction) { |
| 445 errorDictionary[NSLocalizedFailureReasonErrorKey] = contradiction; |
| 446 } |
| 447 |
| 448 return [self createCronetErrorWithCode:CRNErrorUnsupportedConfig |
| 449 userInfo:errorDictionary]; |
| 450 } |
| 451 |
| 452 + (NSError*)createCronetErrorWithCode:(int)errorCode |
| 453 userInfo:(NSDictionary*)userInfo { |
| 417 return [NSError errorWithDomain:CRNCronetErrorDomain | 454 return [NSError errorWithDomain:CRNCronetErrorDomain |
| 418 code:errorCode | 455 code:errorCode |
| 419 userInfo:userInfo]; | 456 userInfo:userInfo]; |
| 420 } | 457 } |
| 421 | 458 |
| 422 @end | 459 @end |
| OLD | NEW |