| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "cronet_test_base.h" |
| 6 |
| 7 #include "components/grpc_support/test/quic_test_server.h" |
| 8 #include "crypto/sha2.h" |
| 9 #include "net/base/net_errors.h" |
| 10 #include "net/cert/asn1_util.h" |
| 11 #include "net/cert/mock_cert_verifier.h" |
| 12 #include "net/test/cert_test_util.h" |
| 13 #include "net/test/test_data_directory.h" |
| 14 |
| 15 #pragma mark |
| 16 |
| 17 @implementation TestDelegate |
| 18 |
| 19 @synthesize semaphore = _semaphore; |
| 20 @synthesize error = _error; |
| 21 @synthesize totalBytesReceived = _totalBytesReceived; |
| 22 |
| 23 NSMutableArray<NSData*>* _responseData; |
| 24 |
| 25 - (id)init { |
| 26 if (self = [super init]) { |
| 27 _semaphore = dispatch_semaphore_create(0); |
| 28 } |
| 29 return self; |
| 30 } |
| 31 |
| 32 - (void)reset { |
| 33 _responseData = nil; |
| 34 _error = nil; |
| 35 _totalBytesReceived = 0; |
| 36 } |
| 37 |
| 38 - (NSString*)responseBody { |
| 39 if (_responseData == nil) { |
| 40 return nil; |
| 41 } |
| 42 NSMutableString* body = [NSMutableString string]; |
| 43 for (NSData* data in _responseData) { |
| 44 [body appendString:[[NSString alloc] initWithData:data |
| 45 encoding:NSUTF8StringEncoding]]; |
| 46 } |
| 47 VLOG(3) << "responseBody size:" << [body length] |
| 48 << " chunks:" << [_responseData count]; |
| 49 return body; |
| 50 } |
| 51 |
| 52 - (void)URLSession:(NSURLSession*)session |
| 53 didBecomeInvalidWithError:(NSError*)error { |
| 54 } |
| 55 |
| 56 - (void)URLSession:(NSURLSession*)session |
| 57 task:(NSURLSessionTask*)task |
| 58 didCompleteWithError:(NSError*)error { |
| 59 [self setError:error]; |
| 60 dispatch_semaphore_signal(_semaphore); |
| 61 } |
| 62 |
| 63 - (void)URLSession:(NSURLSession*)session |
| 64 task:(NSURLSessionTask*)task |
| 65 didReceiveChallenge:(NSURLAuthenticationChallenge*)challenge |
| 66 completionHandler: |
| 67 (void (^)(NSURLSessionAuthChallengeDisposition disp, |
| 68 NSURLCredential* credential))completionHandler { |
| 69 completionHandler(NSURLSessionAuthChallengeUseCredential, nil); |
| 70 } |
| 71 |
| 72 - (void)URLSession:(NSURLSession*)session |
| 73 dataTask:(NSURLSessionDataTask*)dataTask |
| 74 didReceiveResponse:(NSURLResponse*)response |
| 75 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition)) |
| 76 completionHandler { |
| 77 completionHandler(NSURLSessionResponseAllow); |
| 78 } |
| 79 |
| 80 - (void)URLSession:(NSURLSession*)session |
| 81 dataTask:(NSURLSessionDataTask*)dataTask |
| 82 didReceiveData:(NSData*)data { |
| 83 _totalBytesReceived += [data length]; |
| 84 if (_responseData == nil) { |
| 85 _responseData = [[NSMutableArray alloc] init]; |
| 86 } |
| 87 [_responseData addObject:data]; |
| 88 } |
| 89 |
| 90 - (void)URLSession:(NSURLSession*)session |
| 91 dataTask:(NSURLSessionDataTask*)dataTask |
| 92 willCacheResponse:(NSCachedURLResponse*)proposedResponse |
| 93 completionHandler: |
| 94 (void (^)(NSCachedURLResponse* cachedResponse))completionHandler { |
| 95 completionHandler(proposedResponse); |
| 96 } |
| 97 |
| 98 @end |
| 99 |
| 100 namespace cronet { |
| 101 |
| 102 void CronetTestBase::SetUp() { |
| 103 ::testing::Test::SetUp(); |
| 104 grpc_support::StartQuicTestServer(); |
| 105 delegate_ = [[TestDelegate alloc] init]; |
| 106 } |
| 107 |
| 108 void CronetTestBase::TearDown() { |
| 109 grpc_support::ShutdownQuicTestServer(); |
| 110 ::testing::Test::TearDown(); |
| 111 } |
| 112 |
| 113 // Launches the supplied |task| and blocks until it completes, with a timeout |
| 114 // of 1 second. |
| 115 void CronetTestBase::StartDataTaskAndWaitForCompletion( |
| 116 NSURLSessionDataTask* task) { |
| 117 [delegate_ reset]; |
| 118 [task resume]; |
| 119 |
| 120 int64_t deadline_ns = 20 * NSEC_PER_SEC; |
| 121 ASSERT_EQ(0, dispatch_semaphore_wait( |
| 122 [delegate_ semaphore], |
| 123 dispatch_time(DISPATCH_TIME_NOW, deadline_ns))); |
| 124 } |
| 125 |
| 126 ::testing::AssertionResult CronetTestBase::IsResponseSuccessful() { |
| 127 if ([delegate_ error]) |
| 128 return ::testing::AssertionFailure() << "error in response: " << |
| 129 [[[delegate_ error] description] |
| 130 cStringUsingEncoding:NSUTF8StringEncoding]; |
| 131 else |
| 132 return ::testing::AssertionSuccess() << "no errors in response"; |
| 133 } |
| 134 |
| 135 std::unique_ptr<net::MockCertVerifier> CronetTestBase::CreateMockCertVerifier( |
| 136 const std::vector<std::string>& certs, |
| 137 bool known_root) { |
| 138 std::unique_ptr<net::MockCertVerifier> mock_cert_verifier( |
| 139 new net::MockCertVerifier()); |
| 140 for (const auto& cert : certs) { |
| 141 net::CertVerifyResult verify_result; |
| 142 verify_result.verified_cert = |
| 143 net::ImportCertFromFile(net::GetTestCertsDirectory(), cert); |
| 144 |
| 145 // By default, HPKP verification is enabled for known trust roots only. |
| 146 verify_result.is_issued_by_known_root = known_root; |
| 147 |
| 148 // Calculate the public key hash and add it to the verify_result. |
| 149 net::HashValue hashValue; |
| 150 CHECK(CalculatePublicKeySha256(*verify_result.verified_cert.get(), |
| 151 &hashValue)); |
| 152 verify_result.public_key_hashes.push_back(hashValue); |
| 153 |
| 154 mock_cert_verifier->AddResultForCert(verify_result.verified_cert.get(), |
| 155 verify_result, net::OK); |
| 156 } |
| 157 return mock_cert_verifier; |
| 158 } |
| 159 |
| 160 bool CronetTestBase::CalculatePublicKeySha256(const net::X509Certificate& cert, |
| 161 net::HashValue* out_hash_value) { |
| 162 // Convert the cert to DER encoded bytes. |
| 163 std::string der_cert_bytes; |
| 164 net::X509Certificate::OSCertHandle cert_handle = cert.os_cert_handle(); |
| 165 if (!net::X509Certificate::GetDEREncoded(cert_handle, &der_cert_bytes)) { |
| 166 LOG(INFO) << "Unable to convert the given cert to DER encoding"; |
| 167 return false; |
| 168 } |
| 169 // Extract the public key from the cert. |
| 170 base::StringPiece spki_bytes; |
| 171 if (!net::asn1::ExtractSPKIFromDERCert(der_cert_bytes, &spki_bytes)) { |
| 172 LOG(INFO) << "Unable to retrieve the public key from the DER cert"; |
| 173 return false; |
| 174 } |
| 175 // Calculate SHA256 hash of public key bytes. |
| 176 out_hash_value->tag = net::HASH_VALUE_SHA256; |
| 177 crypto::SHA256HashString(spki_bytes, out_hash_value->data(), |
| 178 crypto::kSHA256Length); |
| 179 return true; |
| 180 } |
| 181 |
| 182 } // namespace cronet |
| OLD | NEW |