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

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

Issue 1417003: Revert due to compile failures... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 10 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « net/base/x509_certificate.cc ('k') | net/net.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2006-2008 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 <Security/Security.h>
9 #include <time.h> 8 #include <time.h>
10 9
11 #include "base/scoped_cftyperef.h" 10 #include "base/scoped_cftyperef.h"
12 #include "base/logging.h" 11 #include "base/logging.h"
13 #include "base/pickle.h" 12 #include "base/pickle.h"
14 #include "base/sys_string_conversions.h" 13 #include "base/sys_string_conversions.h"
15 #include "net/base/cert_status_flags.h" 14 #include "net/base/cert_status_flags.h"
16 #include "net/base/cert_verify_result.h" 15 #include "net/base/cert_verify_result.h"
17 #include "net/base/net_errors.h" 16 #include "net/base/net_errors.h"
18 17
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 73
75 void SetMacTestCertificate(X509Certificate* cert) { 74 void SetMacTestCertificate(X509Certificate* cert) {
76 Singleton<MacTrustedCertificates>::get()->SetTestCertificate(cert); 75 Singleton<MacTrustedCertificates>::get()->SetTestCertificate(cert);
77 } 76 }
78 77
79 namespace { 78 namespace {
80 79
81 typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef, 80 typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef,
82 CFDictionaryRef*); 81 CFDictionaryRef*);
83 82
83 inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) {
84 return oid1->Length == oid2->Length &&
85 (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0);
86 }
87
84 int NetErrorFromOSStatus(OSStatus status) { 88 int NetErrorFromOSStatus(OSStatus status) {
85 switch (status) { 89 switch (status) {
86 case noErr: 90 case noErr:
87 return OK; 91 return OK;
88 case errSecNotAvailable: 92 case errSecNotAvailable:
89 case errSecNoCertificateModule: 93 case errSecNoCertificateModule:
90 case errSecNoPolicyModule: 94 case errSecNoPolicyModule:
91 return ERR_NOT_IMPLEMENTED; 95 return ERR_NOT_IMPLEMENTED;
92 case errSecAuthFailed: 96 case errSecAuthFailed:
93 return ERR_ACCESS_DENIED; 97 return ERR_ACCESS_DENIED;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 c != hostname.end() && is_dotted_ip; ++c) 166 c != hostname.end() && is_dotted_ip; ++c)
163 is_dotted_ip = (*c >= '0' && *c <= '9') || *c == '.'; 167 is_dotted_ip = (*c >= '0' && *c <= '9') || *c == '.';
164 if (is_dotted_ip) { 168 if (is_dotted_ip) {
165 for (std::vector<std::string>::const_iterator name = dns_names->begin(); 169 for (std::vector<std::string>::const_iterator name = dns_names->begin();
166 name != dns_names->end() && !override_hostname_mismatch; ++name) 170 name != dns_names->end() && !override_hostname_mismatch; ++name)
167 override_hostname_mismatch = (*name == hostname); 171 override_hostname_mismatch = (*name == hostname);
168 } 172 }
169 return override_hostname_mismatch; 173 return override_hostname_mismatch;
170 } 174 }
171 175
176 void ParsePrincipal(const CSSM_X509_NAME* name,
177 X509Certificate::Principal* principal) {
178 std::vector<std::string> common_names, locality_names, state_names,
179 country_names;
180
181 // TODO(jcampan): add business_category and serial_number.
182 const CSSM_OID* kOIDs[] = { &CSSMOID_CommonName,
183 &CSSMOID_LocalityName,
184 &CSSMOID_StateProvinceName,
185 &CSSMOID_CountryName,
186 &CSSMOID_StreetAddress,
187 &CSSMOID_OrganizationName,
188 &CSSMOID_OrganizationalUnitName,
189 &CSSMOID_DNQualifier }; // This should be "DC"
190 // but is undoubtedly
191 // wrong. TODO(avi):
192 // Find the right OID.
193
194 std::vector<std::string>* values[] = {
195 &common_names, &locality_names,
196 &state_names, &country_names,
197 &(principal->street_addresses),
198 &(principal->organization_names),
199 &(principal->organization_unit_names),
200 &(principal->domain_components) };
201 DCHECK(arraysize(kOIDs) == arraysize(values));
202
203 for (size_t rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
204 CSSM_X509_RDN rdn_struct = name->RelativeDistinguishedName[rdn];
205 for (size_t pair = 0; pair < rdn_struct.numberOfPairs; ++pair) {
206 CSSM_X509_TYPE_VALUE_PAIR pair_struct =
207 rdn_struct.AttributeTypeAndValue[pair];
208 for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
209 if (CSSMOIDEqual(&pair_struct.type, kOIDs[oid])) {
210 std::string value =
211 std::string(reinterpret_cast<std::string::value_type*>
212 (pair_struct.value.Data),
213 pair_struct.value.Length);
214 values[oid]->push_back(value);
215 break;
216 }
217 }
218 }
219 }
220
221 // We don't expect to have more than one CN, L, S, and C.
222 std::vector<std::string>* single_value_lists[4] = {
223 &common_names, &locality_names, &state_names, &country_names };
224 std::string* single_values[4] = {
225 &principal->common_name, &principal->locality_name,
226 &principal->state_or_province_name, &principal->country_name };
227 for (size_t i = 0; i < arraysize(single_value_lists); ++i) {
228 DCHECK(single_value_lists[i]->size() <= 1);
229 if (single_value_lists[i]->size() > 0)
230 *(single_values[i]) = (*(single_value_lists[i]))[0];
231 }
232 }
233
172 struct CSSMFields { 234 struct CSSMFields {
173 CSSMFields() : cl_handle(NULL), num_of_fields(0), fields(NULL) {} 235 CSSMFields() : cl_handle(NULL), num_of_fields(0), fields(NULL) {}
174 ~CSSMFields() { 236 ~CSSMFields() {
175 if (cl_handle) 237 if (cl_handle)
176 CSSM_CL_FreeFields(cl_handle, num_of_fields, &fields); 238 CSSM_CL_FreeFields(cl_handle, num_of_fields, &fields);
177 } 239 }
178 240
179 CSSM_CL_HANDLE cl_handle; 241 CSSM_CL_HANDLE cl_handle;
180 uint32 num_of_fields; 242 uint32 num_of_fields;
181 CSSM_FIELD_PTR fields; 243 CSSM_FIELD_PTR fields;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 }; 379 };
318 err = SecPolicySetValue(*policy, &options_data); 380 err = SecPolicySetValue(*policy, &options_data);
319 if (err) { 381 if (err) {
320 CFRelease(*policy); 382 CFRelease(*policy);
321 return err; 383 return err;
322 } 384 }
323 } 385 }
324 return noErr; 386 return noErr;
325 } 387 }
326 388
327 // Gets the issuer for a given cert, starting with the cert itself and
328 // including the intermediate and finally root certificates (if any).
329 // This function calls SecTrust but doesn't actually pay attention to the trust
330 // result: it shouldn't be used to determine trust, just to traverse the chain.
331 // Caller is responsible for releasing the value stored into *out_cert_chain.
332 OSStatus CopyCertChain(SecCertificateRef cert_handle,
333 CFArrayRef* out_cert_chain) {
334 DCHECK(cert_handle && out_cert_chain);
335 // Create an SSL policy ref configured for client cert evaluation.
336 SecPolicyRef ssl_policy;
337 OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy);
338 if (result)
339 return result;
340 scoped_cftyperef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
341
342 // Create a SecTrustRef.
343 scoped_cftyperef<CFArrayRef> input_certs(
344 CFArrayCreate(NULL, (const void**)&cert_handle, 1,
345 &kCFTypeArrayCallBacks));
346 SecTrustRef trust_ref = NULL;
347 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref);
348 if (result)
349 return result;
350 scoped_cftyperef<SecTrustRef> trust(trust_ref);
351
352 // Evaluate trust, which creates the cert chain.
353 SecTrustResultType status;
354 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
355 result = SecTrustEvaluate(trust, &status);
356 if (result)
357 return result;
358 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain);
359 }
360
361 } // namespace 389 } // namespace
362 390
363 void X509Certificate::Initialize() { 391 void X509Certificate::Initialize() {
364 const CSSM_X509_NAME* name; 392 const CSSM_X509_NAME* name;
365 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); 393 OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
366 if (!status) { 394 if (!status) {
367 subject_.Parse(name); 395 ParsePrincipal(name, &subject_);
368 } 396 }
369 status = SecCertificateGetIssuer(cert_handle_, &name); 397 status = SecCertificateGetIssuer(cert_handle_, &name);
370 if (!status) { 398 if (!status) {
371 issuer_.Parse(name); 399 ParsePrincipal(name, &issuer_);
372 } 400 }
373 401
374 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore, 402 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore,
375 &valid_start_); 403 &valid_start_);
376 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, 404 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter,
377 &valid_expiry_); 405 &valid_expiry_);
378 406
379 fingerprint_ = CalculateFingerprint(cert_handle_); 407 fingerprint_ = CalculateFingerprint(cert_handle_);
380 } 408 }
381 409
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_NetscapeCertType)) { 735 } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_NetscapeCertType)) {
708 uint16_t flags = 736 uint16_t flags =
709 *reinterpret_cast<const uint16_t*>(ext->value.parsedValue); 737 *reinterpret_cast<const uint16_t*>(ext->value.parsedValue);
710 if (flags & CE_NCT_SSL_Client) 738 if (flags & CE_NCT_SSL_Client)
711 return true; 739 return true;
712 } 740 }
713 } 741 }
714 return false; 742 return false;
715 } 743 }
716 744
717 bool X509Certificate::IsIssuedBy(
718 const std::vector<CertPrincipal>& valid_issuers) {
719 // Get the cert's issuer chain.
720 CFArrayRef cert_chain = NULL;
721 OSStatus result;
722 result = CopyCertChain(os_cert_handle(), &cert_chain);
723 if (result != noErr)
724 return false;
725 scoped_cftyperef<CFArrayRef> scoped_cert_chain(cert_chain);
726
727 // Check all the certs in the chain for a match.
728 int n = CFArrayGetCount(cert_chain);
729 for (int i = 0; i < n; ++i) {
730 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>(
731 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i)));
732 CFRetain(cert_handle);
733 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
734 cert_handle,
735 X509Certificate::SOURCE_LONE_CERT_IMPORT,
736 X509Certificate::OSCertHandles());
737 for (unsigned j = 0; j < valid_issuers.size(); j++) {
738 if (cert->subject().Matches(valid_issuers[j]))
739 return true;
740 }
741 }
742 return false;
743 }
744
745 // static 745 // static
746 OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) { 746 OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) {
747 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { 747 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = {
748 CSSM_APPLE_TP_SSL_OPTS_VERSION, 748 CSSM_APPLE_TP_SSL_OPTS_VERSION,
749 0, 749 0,
750 NULL, 750 NULL,
751 CSSM_APPLE_TP_SSL_CLIENT 751 CSSM_APPLE_TP_SSL_CLIENT
752 }; 752 };
753 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, 753 return CreatePolicy(&CSSMOID_APPLE_TP_SSL,
754 &tp_ssl_options, 754 &tp_ssl_options,
755 sizeof(tp_ssl_options), 755 sizeof(tp_ssl_options),
756 out_policy); 756 out_policy);
757 } 757 }
758 758
759 // static 759 // static
760 bool X509Certificate::GetSSLClientCertificates ( 760 bool X509Certificate::GetSSLClientCertificates (
761 const std::string& server_domain, 761 const std::string& server_domain,
762 const std::vector<Principal>& valid_issuers,
763 std::vector<scoped_refptr<X509Certificate> >* certs) { 762 std::vector<scoped_refptr<X509Certificate> >* certs) {
764 scoped_cftyperef<SecIdentityRef> preferred_identity; 763 scoped_cftyperef<SecIdentityRef> preferred_identity;
765 if (!server_domain.empty()) { 764 if (!server_domain.empty()) {
766 // See if there's an identity preference for this domain: 765 // See if there's an identity preference for this domain:
767 scoped_cftyperef<CFStringRef> domain_str( 766 scoped_cftyperef<CFStringRef> domain_str(
768 base::SysUTF8ToCFStringRef("https://" + server_domain)); 767 base::SysUTF8ToCFStringRef("https://" + server_domain));
769 SecIdentityRef identity = NULL; 768 SecIdentityRef identity = NULL;
770 if (SecIdentityCopyPreference(domain_str, 769 if (SecIdentityCopyPreference(domain_str,
771 0, 770 0,
772 NULL, // validIssuers argument is ignored :( 771 NULL,
773 &identity) == noErr) 772 &identity) == noErr)
774 preferred_identity.reset(identity); 773 preferred_identity.reset(identity);
775 } 774 }
776 775
777 // Now enumerate the identities in the available keychains.
778 SecIdentitySearchRef search = nil; 776 SecIdentitySearchRef search = nil;
779 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); 777 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search);
780 scoped_cftyperef<SecIdentitySearchRef> scoped_search(search); 778 scoped_cftyperef<SecIdentitySearchRef> scoped_search(search);
781 while (!err) { 779 while (!err) {
782 SecIdentityRef identity = NULL; 780 SecIdentityRef identity = NULL;
783 err = SecIdentitySearchCopyNext(search, &identity); 781 err = SecIdentitySearchCopyNext(search, &identity);
784 if (err) 782 if (err)
785 break; 783 break;
786 scoped_cftyperef<SecIdentityRef> scoped_identity(identity); 784 scoped_cftyperef<SecIdentityRef> scoped_identity(identity);
787 785
(...skipping 12 matching lines...) Expand all
800 // Skip duplicates (a cert may be in multiple keychains). 798 // Skip duplicates (a cert may be in multiple keychains).
801 X509Certificate::Fingerprint fingerprint = cert->fingerprint(); 799 X509Certificate::Fingerprint fingerprint = cert->fingerprint();
802 unsigned i; 800 unsigned i;
803 for (i = 0; i < certs->size(); ++i) { 801 for (i = 0; i < certs->size(); ++i) {
804 if ((*certs)[i]->fingerprint().Equals(fingerprint)) 802 if ((*certs)[i]->fingerprint().Equals(fingerprint))
805 break; 803 break;
806 } 804 }
807 if (i < certs->size()) 805 if (i < certs->size())
808 continue; 806 continue;
809 807
810 bool is_preferred = preferred_identity &&
811 CFEqual(preferred_identity, identity);
812
813 // Make sure the issuer matches valid_issuers, if given.
814 // But an explicit cert preference overrides this.
815 if (!is_preferred &&
816 valid_issuers.size() > 0 &&
817 !cert->IsIssuedBy(valid_issuers))
818 continue;
819
820 // The cert passes, so add it to the vector. 808 // The cert passes, so add it to the vector.
821 // If it's the preferred identity, add it at the start (so it'll be 809 // If it's the preferred identity, add it at the start (so it'll be
822 // selected by default in the UI.) 810 // selected by default in the UI.)
823 if (is_preferred) 811 if (preferred_identity && CFEqual(preferred_identity, identity))
824 certs->insert(certs->begin(), cert); 812 certs->insert(certs->begin(), cert);
825 else 813 else
826 certs->push_back(cert); 814 certs->push_back(cert);
827 } 815 }
828 816
829 if (err != errSecItemNotFound) { 817 if (err != errSecItemNotFound) {
830 LOG(ERROR) << "SecIdentitySearch error " << err; 818 LOG(ERROR) << "SecIdentitySearch error " << err;
831 return false; 819 return false;
832 } 820 }
833 return true; 821 return true;
834 } 822 }
835 823
836 CFArrayRef X509Certificate::CreateClientCertificateChain() const { 824 CFArrayRef X509Certificate::CreateClientCertificateChain() const {
837 // Initialize the result array with just the IdentityRef of the receiver: 825 // Initialize the result array with just the IdentityRef of the receiver:
838 OSStatus result; 826 OSStatus result;
839 SecIdentityRef identity; 827 SecIdentityRef identity;
840 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); 828 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity);
841 if (result) { 829 if (result) {
842 LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result; 830 LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result;
843 return NULL; 831 return NULL;
844 } 832 }
845 scoped_cftyperef<CFMutableArrayRef> chain( 833 scoped_cftyperef<CFMutableArrayRef> chain(
846 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); 834 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks));
847 CFArrayAppendValue(chain, identity); 835 CFArrayAppendValue(chain, identity);
848 836
849 CFArrayRef cert_chain = NULL; 837 {
850 result = CopyCertChain(cert_handle_, &cert_chain); 838 // Create an SSL policy ref configured for client cert evaluation.
851 if (result) 839 SecPolicyRef ssl_policy;
852 goto exit; 840 result = CreateSSLClientPolicy(&ssl_policy);
841 if (result)
842 goto exit;
843 scoped_cftyperef<SecPolicyRef> scoped_ssl_policy(ssl_policy);
853 844
854 // Append the intermediate certs from SecTrust to the result array: 845 // Use a SecTrust object to find the intermediate certs in the trust chain.
855 if (cert_chain) { 846 scoped_cftyperef<CFArrayRef> input_certs(
856 int chain_count = CFArrayGetCount(cert_chain); 847 CFArrayCreate(NULL, (const void**)&cert_handle_, 1,
857 if (chain_count > 1) { 848 &kCFTypeArrayCallBacks));
858 CFArrayAppendArray(chain, 849 SecTrustRef trust_ref = NULL;
859 cert_chain, 850 result = SecTrustCreateWithCertificates(input_certs,
860 CFRangeMake(1, chain_count - 1)); 851 ssl_policy,
852 &trust_ref);
853 if (result)
854 goto exit;
855 scoped_cftyperef<SecTrustRef> trust(trust_ref);
856
857 SecTrustResultType status;
858 CFArrayRef trust_chain = NULL;
859 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain;
860 result = SecTrustEvaluate(trust, &status);
861 if (result)
862 goto exit;
863 result = SecTrustGetResult(trust, &status, &trust_chain, &status_chain);
864 if (result)
865 goto exit;
866
867 // Append the intermediate certs from SecTrust to the result array:
868 if (trust_chain) {
869 int chain_count = CFArrayGetCount(trust_chain);
870 if (chain_count > 1) {
871 CFArrayAppendArray(chain,
872 trust_chain,
873 CFRangeMake(1, chain_count - 1));
874 }
875 CFRelease(trust_chain);
861 } 876 }
862 CFRelease(cert_chain);
863 } 877 }
864 exit: 878 exit:
865 if (result) 879 if (result)
866 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; 880 LOG(ERROR) << "CreateIdentityCertificateChain error " << result;
867 return chain.release(); 881 return chain.release();
868 } 882 }
869 883
870 } // namespace net 884 } // namespace net
OLDNEW
« no previous file with comments | « net/base/x509_certificate.cc ('k') | net/net.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698