Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: net/base/x509_certificate_mac.cc

Issue 12035105: Move client certificates retrieval logic out of the SSL sockets. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Linux Redux build Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 #include "net/base/x509_certificate.h" 5 #include "net/base/x509_certificate.h"
6 6
7 #include <CommonCrypto/CommonDigest.h> 7 #include <CommonCrypto/CommonDigest.h>
8 #include <CoreServices/CoreServices.h> 8 #include <CoreServices/CoreServices.h>
9 #include <Security/Security.h> 9 #include <Security/Security.h>
10 #include <time.h> 10 #include <time.h>
(...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 if (status == CSSM_OK && key_usage.field()) { 705 if (status == CSSM_OK && key_usage.field()) {
706 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); 706 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
707 const CE_ExtendedKeyUsage* ext_key_usage = 707 const CE_ExtendedKeyUsage* ext_key_usage =
708 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); 708 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
709 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) 709 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth))
710 return false; 710 return false;
711 } 711 }
712 return true; 712 return true;
713 } 713 }
714 714
715 bool X509Certificate::IsIssuedBy(
716 const std::vector<CertPrincipal>& valid_issuers) {
717 // Get the cert's issuer chain.
718 CFArrayRef cert_chain = NULL;
719 OSStatus result = CopyCertChain(os_cert_handle(), &cert_chain);
720 if (result)
721 return false;
722 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain);
723
724 // Check all the certs in the chain for a match.
725 int n = CFArrayGetCount(cert_chain);
726 for (int i = 0; i < n; ++i) {
727 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>(
728 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
729 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle(
730 cert_handle, X509Certificate::OSCertHandles()));
731 for (unsigned j = 0; j < valid_issuers.size(); j++) {
732 if (cert->issuer().Matches(valid_issuers[j]))
733 return true;
734 }
735 }
736 return false;
737 }
738
739 // static
740 bool X509Certificate::GetSSLClientCertificates(
741 const std::string& server_domain,
742 const std::vector<CertPrincipal>& valid_issuers,
743 CertificateList* certs) {
744 ScopedCFTypeRef<SecIdentityRef> preferred_identity;
745 if (!server_domain.empty()) {
746 // See if there's an identity preference for this domain:
747 ScopedCFTypeRef<CFStringRef> domain_str(
748 base::SysUTF8ToCFStringRef("https://" + server_domain));
749 SecIdentityRef identity = NULL;
750 // While SecIdentityCopyPreferences appears to take a list of CA issuers
751 // to restrict the identity search to, within Security.framework the
752 // argument is ignored and filtering unimplemented. See
753 // SecIdentity.cpp in libsecurity_keychain, specifically
754 // _SecIdentityCopyPreferenceMatchingName().
755 {
756 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
757 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr)
758 preferred_identity.reset(identity);
759 }
760 }
761
762 // Now enumerate the identities in the available keychains.
763 SecIdentitySearchRef search = NULL;
764 OSStatus err;
765 {
766 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
767 err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
768 }
769 if (err)
770 return false;
771 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search);
772 while (!err) {
773 SecIdentityRef identity = NULL;
774 {
775 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
776 err = SecIdentitySearchCopyNext(search, &identity);
777 }
778 if (err)
779 break;
780 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity);
781
782 SecCertificateRef cert_handle;
783 err = SecIdentityCopyCertificate(identity, &cert_handle);
784 if (err != noErr)
785 continue;
786 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle);
787
788 scoped_refptr<X509Certificate> cert(
789 CreateFromHandle(cert_handle, OSCertHandles()));
790 if (cert->HasExpired() || !cert->SupportsSSLClientAuth())
791 continue;
792
793 // Skip duplicates (a cert may be in multiple keychains).
794 const SHA1HashValue& fingerprint = cert->fingerprint();
795 unsigned i;
796 for (i = 0; i < certs->size(); ++i) {
797 if ((*certs)[i]->fingerprint().Equals(fingerprint))
798 break;
799 }
800 if (i < certs->size())
801 continue;
802
803 bool is_preferred = preferred_identity &&
804 CFEqual(preferred_identity, identity);
805
806 // Make sure the issuer matches valid_issuers, if given.
807 if (!valid_issuers.empty() && !cert->IsIssuedBy(valid_issuers))
808 continue;
809
810 // The cert passes, so add it to the vector.
811 // If it's the preferred identity, add it at the start (so it'll be
812 // selected by default in the UI.)
813 if (is_preferred)
814 certs->insert(certs->begin(), cert);
815 else
816 certs->push_back(cert);
817 }
818
819 if (err != errSecItemNotFound) {
820 OSSTATUS_LOG(ERROR, err) << "SecIdentitySearch error";
821 return false;
822 }
823 return true;
824 }
825
826 CFArrayRef X509Certificate::CreateClientCertificateChain() const { 715 CFArrayRef X509Certificate::CreateClientCertificateChain() const {
827 // Initialize the result array with just the IdentityRef of the receiver: 716 // Initialize the result array with just the IdentityRef of the receiver:
828 SecIdentityRef identity; 717 SecIdentityRef identity;
829 OSStatus result; 718 OSStatus result;
830 { 719 {
831 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); 720 base::AutoLock lock(crypto::GetMacSecurityServicesLock());
832 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); 721 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity);
833 } 722 }
834 if (result) { 723 if (result) {
835 OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error"; 724 OSSTATUS_LOG(ERROR, result) << "SecIdentityCreateWithCertificate error";
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
936 *type = kPublicKeyTypeDH; 825 *type = kPublicKeyTypeDH;
937 break; 826 break;
938 default: 827 default:
939 *type = kPublicKeyTypeUnknown; 828 *type = kPublicKeyTypeUnknown;
940 *size_bits = 0; 829 *size_bits = 0;
941 break; 830 break;
942 } 831 }
943 } 832 }
944 833
945 } // namespace net 834 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698