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