Chromium Code Reviews| Index: net/ssl/client_cert_store_mac.cc |
| diff --git a/net/ssl/client_cert_store_mac.cc b/net/ssl/client_cert_store_mac.cc |
| index 7fadb337f1e7735ae8ffd340c81c93c95588d7c4..d69ebbc0f1573001e6c79edf3a24e6199dbe1182 100644 |
| --- a/net/ssl/client_cert_store_mac.cc |
| +++ b/net/ssl/client_cert_store_mac.cc |
| @@ -284,29 +284,7 @@ void ClientCertStoreMac::GetClientCerts( |
| if (err) |
| break; |
| ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); |
| - |
| - SecCertificateRef cert_handle; |
| - err = SecIdentityCopyCertificate(identity, &cert_handle); |
| - if (err != noErr) |
| - continue; |
| - ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); |
| - |
| - if (!SupportsSSLClientAuth(cert_handle)) |
| - continue; |
| - |
| - scoped_refptr<X509Certificate> cert( |
| - x509_util::CreateX509CertificateFromSecCertificate( |
| - cert_handle, std::vector<SecCertificateRef>())); |
| - if (!cert) |
| - continue; |
| - |
| - if (preferred_identity && CFEqual(preferred_identity, identity)) { |
| - // Only one certificate should match. |
| - DCHECK(!preferred_cert.get()); |
| - preferred_cert = cert; |
| - } else { |
| - regular_certs.push_back(cert); |
| - } |
| + AddIdentity(regular_certs, preferred_cert, preferred_identity.get(), identity); |
| } |
| if (err != errSecItemNotFound) { |
| @@ -315,12 +293,74 @@ void ClientCertStoreMac::GetClientCerts( |
| return; |
| } |
| + // For reasons I don't understand, macOS has two different ways of querying |
| + // for client certificate identities. The way we just tried will miss some |
| + // smart card based certificates, and this way misses some soft certificates. |
|
Ryan Sleevi
2017/05/30 18:00:01
We try to avoid pronouns in comments (I/we) and tr
agaynor
2017/05/31 02:37:33
Done.
|
| + const void *keys[] = { |
|
Ryan Sleevi
2017/05/30 18:00:01
You can use "git cl format" to ensure this is prop
Ryan Sleevi
2017/05/30 18:00:01
So, I _believe_ for correctness, that kSecAttrCanS
agaynor
2017/05/31 02:37:33
Done.
agaynor
2017/05/31 02:37:33
It's a boring old RSA key. I've added |kSecAttrCan
mattm
2017/06/05 23:34:27
Looking at that code a bit, it seems that SecItemC
|
| + kSecClass, |
| + kSecMatchLimit, |
| + kSecReturnRef, |
| + }; |
| + const void *values[] = { |
| + kSecClassIdentity, |
| + kSecMatchLimitAll, |
| + kCFBooleanTrue, |
| + }; |
| + CFDictionaryRef query = CFDictionaryCreate( |
|
Ryan Sleevi
2017/05/30 18:00:01
You can see we used the ScopedCFTypeRef C++ helper
agaynor
2017/05/31 02:37:33
Done.
|
| + kCFAllocatorDefault, |
| + keys, |
| + values, |
| + sizeof(values) / sizeof(values[0]), |
| + &kCFTypeDictionaryKeyCallBacks, |
| + &kCFTypeDictionaryValueCallBacks |
| + ); |
| + CFArrayRef result = NULL; |
| + err = SecItemCopyMatching(query, (CFTypeRef *)&result); |
|
Ryan Sleevi
2017/05/30 18:00:00
Note: Chromium explicitly uses C++ casts rather th
agaynor
2017/05/31 02:37:33
Done.
|
| + if (!err) { |
|
Ryan Sleevi
2017/05/30 18:00:01
In general, we try to handle the error case first,
|
| + for (CFIndex i = 0; i < CFArrayGetCount(result); i++) { |
| + CFTypeRef item = CFArrayGetValueAtIndex(result, i); |
| + AddIdentity(regular_certs, preferred_cert, preferred_identity, (SecIdentityRef)item); |
| + } |
| + } |
| + CFRelease(query); |
| + CFRelease(result); |
| + |
| CertificateList selected_certs; |
| GetClientCertsImpl(preferred_cert, regular_certs, request, true, |
| &selected_certs); |
| callback.Run(std::move(selected_certs)); |
| } |
| +void ClientCertStoreMac::AddIdentity( |
| + CertificateList& regular_certs, |
| + scoped_refptr<X509Certificate>& preferred_cert, |
| + SecIdentityRef preferred_identity, |
| + SecIdentityRef identity) { |
| + OSStatus err; |
| + SecCertificateRef cert_handle; |
|
Ryan Sleevi
2017/05/30 18:00:01
.InitializeInto :)
agaynor
2017/05/31 02:37:33
Done.
|
| + err = SecIdentityCopyCertificate(identity, &cert_handle); |
| + if (err != noErr) |
| + return; |
| + ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); |
| + |
| + if (!SupportsSSLClientAuth(cert_handle)) |
| + return; |
| + |
| + scoped_refptr<X509Certificate> cert( |
| + x509_util::CreateX509CertificateFromSecCertificate( |
| + cert_handle, std::vector<SecCertificateRef>())); |
| + if (!cert) |
| + return; |
| + |
| + if (preferred_identity && CFEqual(preferred_identity, identity)) { |
| + // Only one certificate should match. |
| + DCHECK(!preferred_cert.get()); |
| + preferred_cert = cert; |
| + } else { |
| + regular_certs.push_back(cert); |
| + } |
| +} |
| + |
| bool ClientCertStoreMac::SelectClientCertsForTesting( |
| const CertificateList& input_certs, |
| const SSLCertRequestInfo& request, |