1 // Copyright 2014 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.
5 #import "ios/web/web_state/wk_web_view_ssl_error_util.h"
7 #include "base/strings/sys_string_conversions.h"
8 #include "net/cert/x509_certificate.h"
9 #include "net/ssl/ssl_info.h"
13 // This key was determined by inspecting userInfo dict of an SSL error.
14 NSString* const kNSErrorPeerCertificateChainKey =
15 @"NSErrorPeerCertificateChainKey";
21 // Creates certificate from subject string.
22 net::X509Certificate* CreateCertFromSubject(NSString* subject) {
23 std::string issuer = "";
24 base::Time start_date;
25 base::Time expiration_date;
26 return new net::X509Certificate(base::SysNSStringToUTF8(subject),
32 // Creates certificate from array of SecCertificateRef objects.
33 net::X509Certificate* CreateCertFromChain(NSArray* certs) {
36 net::X509Certificate::OSCertHandles intermediates;
37 for (NSUInteger i = 1; i < certs.count; i++) {
38 intermediates.push_back(reinterpret_cast<SecCertificateRef>(certs[i]));
40 return net::X509Certificate::CreateFromHandle(
41 reinterpret_cast<SecCertificateRef>(certs[0]), intermediates);
44 // Creates certificate using information extracted from NSError.
45 net::X509Certificate* CreateCertFromSSLError(NSError* error) {
46 net::X509Certificate* cert = CreateCertFromChain(
47 error.userInfo[web::kNSErrorPeerCertificateChainKey]);
50 return CreateCertFromSubject(
51 error.userInfo[NSURLErrorFailingURLStringErrorKey]);
54 // Maps NSError code to net::CertStatus.
55 net::CertStatus GetCertStatusFromNSErrorCode(NSInteger code) {
57 // Regardless of real certificate problem the system always returns
58 // NSURLErrorServerCertificateUntrusted. The mapping is done in case this
59 // bug is fixed (rdar://18517043).
60 case NSURLErrorServerCertificateUntrusted:
61 case NSURLErrorSecureConnectionFailed:
62 case NSURLErrorServerCertificateHasUnknownRoot:
63 case NSURLErrorClientCertificateRejected:
64 case NSURLErrorClientCertificateRequired:
65 return net::CERT_STATUS_INVALID;
66 case NSURLErrorServerCertificateHasBadDate:
67 case NSURLErrorServerCertificateNotYetValid:
68 return net::CERT_STATUS_DATE_INVALID;
79 BOOL IsWKWebViewSSLError(NSError* error) {
80 // SSL errors range is (-2000..-1200], represented by kCFURLError constants:
81 // (kCFURLErrorCannotLoadFromNetwork..kCFURLErrorSecureConnectionFailed].
82 // It's reasonable to expect that all SSL errors will have the error code
83 // less or equal to NSURLErrorSecureConnectionFailed but greater than
84 // NSURLErrorCannotLoadFromNetwork.
85 return [error.domain isEqualToString:NSURLErrorDomain] &&
86 (error.code <= NSURLErrorSecureConnectionFailed &&
87 NSURLErrorCannotLoadFromNetwork < error.code);
90 void GetSSLInfoFromWKWebViewSSLError(NSError* error, net::SSLInfo* ssl_info) {
91 DCHECK(IsWKWebViewSSLError(error));
92 ssl_info->cert_status = GetCertStatusFromNSErrorCode(error.code);
93 ssl_info->cert = CreateCertFromSSLError(error);