| 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 "ios/web/net/crw_ssl_status_updater.h" | 5 #import "ios/web/net/crw_ssl_status_updater.h" |
| 6 | 6 |
| 7 #import "base/ios/weak_nsobject.h" | 7 #import "base/ios/weak_nsobject.h" |
| 8 #import "base/mac/scoped_nsobject.h" | 8 #import "base/mac/scoped_nsobject.h" |
| 9 #import "base/strings/sys_string_conversions.h" | 9 #import "base/strings/sys_string_conversions.h" |
| 10 #include "ios/web/public/cert_store.h" | 10 #include "ios/web/public/cert_store.h" |
| 11 #import "ios/web/public/navigation_item.h" | 11 #import "ios/web/public/navigation_item.h" |
| 12 #import "ios/web/public/navigation_manager.h" | 12 #import "ios/web/public/navigation_manager.h" |
| 13 #include "ios/web/public/ssl_status.h" | 13 #include "ios/web/public/ssl_status.h" |
| 14 #import "ios/web/web_state/wk_web_view_security_util.h" | 14 #import "ios/web/web_state/wk_web_view_security_util.h" |
| 15 #include "net/cert/x509_certificate.h" | 15 #include "net/cert/x509_certificate.h" |
| 16 #include "url/gurl.h" | 16 #include "url/gurl.h" |
| 17 | 17 |
| 18 using base::ScopedCFTypeRef; |
| 18 using net::CertStatus; | 19 using net::CertStatus; |
| 19 using web::SecurityStyle; | 20 using web::SecurityStyle; |
| 20 | 21 |
| 21 @interface CRWSSLStatusUpdater () { | 22 @interface CRWSSLStatusUpdater () { |
| 22 // DataSource for CRWSSLStatusUpdater. | 23 // DataSource for CRWSSLStatusUpdater. |
| 23 base::WeakNSProtocol<id<CRWSSLStatusUpdaterDataSource>> _dataSource; | 24 base::WeakNSProtocol<id<CRWSSLStatusUpdaterDataSource>> _dataSource; |
| 24 // Backs up property of the same name. | 25 // Backs up property of the same name. |
| 25 base::WeakNSProtocol<id<CRWSSLStatusUpdaterDelegate>> _delegate; | 26 base::WeakNSProtocol<id<CRWSSLStatusUpdaterDelegate>> _delegate; |
| 26 } | 27 } |
| 27 | 28 |
| 28 // Unowned pointer to web::NavigationManager. | 29 // Unowned pointer to web::NavigationManager. |
| 29 @property(nonatomic, readonly) web::NavigationManager* navigationManager; | 30 @property(nonatomic, readonly) web::NavigationManager* navigationManager; |
| 30 | 31 |
| 31 // Identifier used for storing and retrieving certificates. | 32 // Identifier used for storing and retrieving certificates. |
| 32 @property(nonatomic, readonly) int certGroupID; | 33 @property(nonatomic, readonly) int certGroupID; |
| 33 | 34 |
| 34 // Updates |security_style| and |cert_status| for the NavigationItem with ID | 35 // Updates |security_style| and |cert_status| for the NavigationItem with ID |
| 35 // |navigationItemID|, if URL and certificate chain still match |host| and | 36 // |navigationItemID|, if URL and certificate chain still match |host| and |
| 36 // |certChain|. | 37 // |certChain|. |
| 37 - (void)updateSSLStatusForNavigationItemWithID:(int)navigationItemID | 38 - (void)updateSSLStatusForItemWithID:(int)navigationItemID |
| 38 certChain:(NSArray*)chain | 39 trust:(ScopedCFTypeRef<SecTrustRef>)trust |
| 39 host:(NSString*)host | 40 host:(NSString*)host |
| 40 withSecurityStyle:(SecurityStyle)style | 41 withSecurityStyle:(SecurityStyle)style |
| 41 certStatus:(CertStatus)certStatus; | 42 certStatus:(CertStatus)certStatus; |
| 42 | 43 |
| 43 // Asynchronously obtains SSL status from given |certChain| and |host| and | 44 // Asynchronously obtains SSL status from given |secTrust| and |host| and |
| 44 // updates current navigation item. Before scheduling update changes SSLStatus' | 45 // updates current navigation item. Before scheduling update changes SSLStatus' |
| 45 // cert_status and security_style to default. | 46 // cert_status and security_style to default. |
| 46 - (void)scheduleSSLStatusUpdateUsingCertChain:(NSArray*)chain | 47 - (void)scheduleSSLStatusUpdateUsingTrust:(ScopedCFTypeRef<SecTrustRef>)trust |
| 47 host:(NSString*)host; | 48 host:(NSString*)host; |
| 48 | 49 |
| 49 // Notifies delegate about SSLStatus change. | 50 // Notifies delegate about SSLStatus change. |
| 50 - (void)didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navItem; | 51 - (void)didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navItem; |
| 51 | 52 |
| 52 @end | 53 @end |
| 53 | 54 |
| 54 @implementation CRWSSLStatusUpdater | 55 @implementation CRWSSLStatusUpdater |
| 55 @synthesize navigationManager = _navigationManager; | 56 @synthesize navigationManager = _navigationManager; |
| 56 @synthesize certGroupID = _certGroupID; | 57 @synthesize certGroupID = _certGroupID; |
| 57 | 58 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 74 - (id<CRWSSLStatusUpdaterDelegate>)delegate { | 75 - (id<CRWSSLStatusUpdaterDelegate>)delegate { |
| 75 return _delegate.get(); | 76 return _delegate.get(); |
| 76 } | 77 } |
| 77 | 78 |
| 78 - (void)setDelegate:(id<CRWSSLStatusUpdaterDelegate>)delegate { | 79 - (void)setDelegate:(id<CRWSSLStatusUpdaterDelegate>)delegate { |
| 79 _delegate.reset(delegate); | 80 _delegate.reset(delegate); |
| 80 } | 81 } |
| 81 | 82 |
| 82 - (void)updateSSLStatusForNavigationItem:(web::NavigationItem*)item | 83 - (void)updateSSLStatusForNavigationItem:(web::NavigationItem*)item |
| 83 withCertHost:(NSString*)host | 84 withCertHost:(NSString*)host |
| 84 certChain:(NSArray*)chain | 85 trust:(ScopedCFTypeRef<SecTrustRef>)trust |
| 85 hasOnlySecureContent:(BOOL)hasOnlySecureContent { | 86 hasOnlySecureContent:(BOOL)hasOnlySecureContent { |
| 86 web::SSLStatus previousSSLStatus = item->GetSSL(); | 87 web::SSLStatus previousSSLStatus = item->GetSSL(); |
| 87 | 88 |
| 88 // Starting from iOS9 WKWebView blocks active mixed content, so if | 89 // Starting from iOS9 WKWebView blocks active mixed content, so if |
| 89 // |hasOnlySecureContent| returns NO it means passive content. | 90 // |hasOnlySecureContent| returns NO it means passive content. |
| 90 item->GetSSL().content_status = | 91 item->GetSSL().content_status = |
| 91 hasOnlySecureContent ? web::SSLStatus::NORMAL_CONTENT | 92 hasOnlySecureContent ? web::SSLStatus::NORMAL_CONTENT |
| 92 : web::SSLStatus::DISPLAYED_INSECURE_CONTENT; | 93 : web::SSLStatus::DISPLAYED_INSECURE_CONTENT; |
| 93 | 94 |
| 94 // Try updating SSLStatus for current NavigationItem asynchronously. | 95 // Try updating SSLStatus for current NavigationItem asynchronously. |
| 95 scoped_refptr<net::X509Certificate> cert; | 96 scoped_refptr<net::X509Certificate> cert; |
| 96 if (item->GetURL().SchemeIsCryptographic()) { | 97 if (item->GetURL().SchemeIsCryptographic()) { |
| 97 cert = web::CreateCertFromChain(chain); | 98 cert = web::CreateCertFromTrust(trust); |
| 98 if (cert) { | 99 if (cert) { |
| 99 int oldCertID = item->GetSSL().cert_id; | 100 int oldCertID = item->GetSSL().cert_id; |
| 100 std::string oldHost = item->GetSSL().cert_status_host; | 101 std::string oldHost = item->GetSSL().cert_status_host; |
| 101 item->GetSSL().cert_id = web::CertStore::GetInstance()->StoreCert( | 102 item->GetSSL().cert_id = web::CertStore::GetInstance()->StoreCert( |
| 102 cert.get(), self.certGroupID); | 103 cert.get(), self.certGroupID); |
| 103 item->GetSSL().cert_status_host = base::SysNSStringToUTF8(host); | 104 item->GetSSL().cert_status_host = base::SysNSStringToUTF8(host); |
| 104 // Only recompute the SSLStatus information if the certificate or host has | 105 // Only recompute the SSLStatus information if the certificate or host has |
| 105 // since changed. Host can be changed in case of redirect. | 106 // since changed. Host can be changed in case of redirect. |
| 106 if (oldCertID != item->GetSSL().cert_id || | 107 if (oldCertID != item->GetSSL().cert_id || |
| 107 oldHost != item->GetSSL().cert_status_host) { | 108 oldHost != item->GetSSL().cert_status_host) { |
| 108 // Real SSL status is unknown, reset cert status and security style. | 109 // Real SSL status is unknown, reset cert status and security style. |
| 109 // They will be asynchronously updated in | 110 // They will be asynchronously updated in |
| 110 // |scheduleSSLStatusUpdateUsingCertChain|. | 111 // |scheduleSSLStatusUpdateUsingTrust:host:|. |
| 111 item->GetSSL().cert_status = CertStatus(); | 112 item->GetSSL().cert_status = CertStatus(); |
| 112 item->GetSSL().security_style = web::SECURITY_STYLE_UNKNOWN; | 113 item->GetSSL().security_style = web::SECURITY_STYLE_UNKNOWN; |
| 113 | 114 |
| 114 [self scheduleSSLStatusUpdateUsingCertChain:chain host:host]; | 115 [self scheduleSSLStatusUpdateUsingTrust:std::move(trust) host:host]; |
| 115 } | 116 } |
| 116 } | 117 } |
| 117 } | 118 } |
| 118 | 119 |
| 119 if (!cert) { | 120 if (!cert) { |
| 120 item->GetSSL().cert_id = 0; | 121 item->GetSSL().cert_id = 0; |
| 121 if (!item->GetURL().SchemeIsCryptographic()) { | 122 if (!item->GetURL().SchemeIsCryptographic()) { |
| 122 // HTTP or other non-secure connection. | 123 // HTTP or other non-secure connection. |
| 123 item->GetSSL().security_style = web::SECURITY_STYLE_UNAUTHENTICATED; | 124 item->GetSSL().security_style = web::SECURITY_STYLE_UNAUTHENTICATED; |
| 124 } else { | 125 } else { |
| 125 // HTTPS, no certificate (this use-case has not been observed). | 126 // HTTPS, no certificate (this use-case has not been observed). |
| 126 item->GetSSL().security_style = web::SECURITY_STYLE_UNKNOWN; | 127 item->GetSSL().security_style = web::SECURITY_STYLE_UNKNOWN; |
| 127 } | 128 } |
| 128 } | 129 } |
| 129 | 130 |
| 130 if (!previousSSLStatus.Equals(item->GetSSL())) { | 131 if (!previousSSLStatus.Equals(item->GetSSL())) { |
| 131 [self didChangeSSLStatusForNavigationItem:item]; | 132 [self didChangeSSLStatusForNavigationItem:item]; |
| 132 } | 133 } |
| 133 } | 134 } |
| 134 | 135 |
| 135 #pragma mark - Private | 136 #pragma mark - Private |
| 136 | 137 |
| 137 - (void)updateSSLStatusForNavigationItemWithID:(int)navigationItemID | 138 - (void)updateSSLStatusForItemWithID:(int)navigationItemID |
| 138 certChain:(NSArray*)chain | 139 trust:(ScopedCFTypeRef<SecTrustRef>)trust |
| 139 host:(NSString*)host | 140 host:(NSString*)host |
| 140 withSecurityStyle:(SecurityStyle)style | 141 withSecurityStyle:(SecurityStyle)style |
| 141 certStatus:(CertStatus)certStatus { | 142 certStatus:(CertStatus)certStatus { |
| 142 // The searched item almost always be the last one, so walk backward rather | 143 // The searched item almost always be the last one, so walk backward rather |
| 143 // than forward. | 144 // than forward. |
| 144 for (int i = _navigationManager->GetItemCount() - 1; 0 <= i; i--) { | 145 for (int i = _navigationManager->GetItemCount() - 1; 0 <= i; i--) { |
| 145 web::NavigationItem* item = _navigationManager->GetItemAtIndex(i); | 146 web::NavigationItem* item = _navigationManager->GetItemAtIndex(i); |
| 146 if (item->GetUniqueID() != navigationItemID) | 147 if (item->GetUniqueID() != navigationItemID) |
| 147 continue; | 148 continue; |
| 148 | 149 |
| 149 // NavigationItem's UniqueID is preserved even after redirects, so | 150 // NavigationItem's UniqueID is preserved even after redirects, so |
| 150 // checking that cert and URL match is necessary. | 151 // checking that cert and URL match is necessary. |
| 151 scoped_refptr<net::X509Certificate> cert(web::CreateCertFromChain(chain)); | 152 scoped_refptr<net::X509Certificate> cert(web::CreateCertFromTrust(trust)); |
| 152 int certID = | 153 int certID = |
| 153 web::CertStore::GetInstance()->StoreCert(cert.get(), self.certGroupID); | 154 web::CertStore::GetInstance()->StoreCert(cert.get(), self.certGroupID); |
| 154 std::string GURLHost = base::SysNSStringToUTF8(host); | 155 std::string GURLHost = base::SysNSStringToUTF8(host); |
| 155 web::SSLStatus& SSLStatus = item->GetSSL(); | 156 web::SSLStatus& SSLStatus = item->GetSSL(); |
| 156 if (item->GetURL().SchemeIsCryptographic() && SSLStatus.cert_id == certID && | 157 if (item->GetURL().SchemeIsCryptographic() && SSLStatus.cert_id == certID && |
| 157 item->GetURL().host() == GURLHost) { | 158 item->GetURL().host() == GURLHost) { |
| 158 web::SSLStatus previousSSLStatus = item->GetSSL(); | 159 web::SSLStatus previousSSLStatus = item->GetSSL(); |
| 159 SSLStatus.cert_status = certStatus; | 160 SSLStatus.cert_status = certStatus; |
| 160 SSLStatus.security_style = style; | 161 SSLStatus.security_style = style; |
| 161 if (!previousSSLStatus.Equals(SSLStatus)) { | 162 if (!previousSSLStatus.Equals(SSLStatus)) { |
| 162 [self didChangeSSLStatusForNavigationItem:item]; | 163 [self didChangeSSLStatusForNavigationItem:item]; |
| 163 } | 164 } |
| 164 } | 165 } |
| 165 return; | 166 return; |
| 166 } | 167 } |
| 167 } | 168 } |
| 168 | 169 |
| 169 - (void)scheduleSSLStatusUpdateUsingCertChain:(NSArray*)chain | 170 - (void)scheduleSSLStatusUpdateUsingTrust:(ScopedCFTypeRef<SecTrustRef>)trust |
| 170 host:(NSString*)host { | 171 host:(NSString*)host { |
| 171 // Use Navigation Item's unique ID to locate requested item after | 172 // Use Navigation Item's unique ID to locate requested item after |
| 172 // obtaining cert status asynchronously. | 173 // obtaining cert status asynchronously. |
| 173 int itemID = _navigationManager->GetLastCommittedItem()->GetUniqueID(); | 174 int itemID = _navigationManager->GetLastCommittedItem()->GetUniqueID(); |
| 174 | 175 |
| 175 DCHECK(_dataSource); | 176 DCHECK(_dataSource); |
| 176 base::WeakNSObject<CRWSSLStatusUpdater> weakSelf(self); | 177 base::WeakNSObject<CRWSSLStatusUpdater> weakSelf(self); |
| 177 [_dataSource SSLStatusUpdater:self | 178 [_dataSource SSLStatusUpdater:self |
| 178 querySSLStatusForCertChain:chain | 179 querySSLStatusForTrust:trust |
| 179 host:host | 180 host:host |
| 180 completionHandler:^(SecurityStyle style, CertStatus certStatus) { | 181 completionHandler:^(SecurityStyle style, CertStatus certStatus) { |
| 181 [weakSelf updateSSLStatusForNavigationItemWithID:itemID | 182 [weakSelf updateSSLStatusForItemWithID:itemID |
| 182 certChain:chain | 183 trust:std::move(trust) |
| 183 host:host | 184 host:host |
| 184 withSecurityStyle:style | 185 withSecurityStyle:style |
| 185 certStatus:certStatus]; | 186 certStatus:certStatus]; |
| 186 }]; | 187 }]; |
| 187 } | 188 } |
| 188 | 189 |
| 189 - (void)didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navItem { | 190 - (void)didChangeSSLStatusForNavigationItem:(web::NavigationItem*)navItem { |
| 190 if ([_delegate respondsToSelector: | 191 if ([_delegate respondsToSelector: |
| 191 @selector(SSLStatusUpdater:didChangeSSLStatusForNavigationItem:)]) { | 192 @selector(SSLStatusUpdater:didChangeSSLStatusForNavigationItem:)]) { |
| 192 [_delegate SSLStatusUpdater:self | 193 [_delegate SSLStatusUpdater:self |
| 193 didChangeSSLStatusForNavigationItem:navItem]; | 194 didChangeSSLStatusForNavigationItem:navItem]; |
| 194 } | 195 } |
| 195 } | 196 } |
| 196 | 197 |
| 197 @end | 198 @end |
| OLD | NEW |