| OLD | NEW |
| 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> | 8 #include <Security/Security.h> |
| 9 #include <time.h> | 9 #include <time.h> |
| 10 | 10 |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 name_type == GNT_URI); | 215 name_type == GNT_URI); |
| 216 | 216 |
| 217 CSSMFields fields; | 217 CSSMFields fields; |
| 218 OSStatus status = GetCertFields(cert_handle, &fields); | 218 OSStatus status = GetCertFields(cert_handle, &fields); |
| 219 if (status) | 219 if (status) |
| 220 return; | 220 return; |
| 221 | 221 |
| 222 for (size_t field = 0; field < fields.num_of_fields; ++field) { | 222 for (size_t field = 0; field < fields.num_of_fields; ++field) { |
| 223 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { | 223 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { |
| 224 CSSM_X509_EXTENSION_PTR cssm_ext = | 224 CSSM_X509_EXTENSION_PTR cssm_ext = |
| 225 (CSSM_X509_EXTENSION_PTR)fields.fields[field].FieldValue.Data; | 225 reinterpret_cast<CSSM_X509_EXTENSION_PTR>( |
| 226 fields.fields[field].FieldValue.Data); |
| 226 CE_GeneralNames* alt_name = | 227 CE_GeneralNames* alt_name = |
| 227 (CE_GeneralNames*) cssm_ext->value.parsedValue; | 228 reinterpret_cast<CE_GeneralNames*>(cssm_ext->value.parsedValue); |
| 228 | 229 |
| 229 for (size_t name = 0; name < alt_name->numNames; ++name) { | 230 for (size_t name = 0; name < alt_name->numNames; ++name) { |
| 230 const CE_GeneralName& name_struct = alt_name->generalName[name]; | 231 const CE_GeneralName& name_struct = alt_name->generalName[name]; |
| 231 // All of the general name types we support are encoded as | 232 // All of the general name types we support are encoded as |
| 232 // IA5String. In general, we should be switching off | 233 // IA5String. In general, we should be switching off |
| 233 // |name_struct.nameType| and doing type-appropriate conversions. See | 234 // |name_struct.nameType| and doing type-appropriate conversions. See |
| 234 // certextensions.h and the comment immediately preceding | 235 // certextensions.h and the comment immediately preceding |
| 235 // CE_GeneralNameType for more information. | 236 // CE_GeneralNameType for more information. |
| 236 if (name_struct.nameType == name_type) { | 237 if (name_struct.nameType == name_type) { |
| 237 const CSSM_DATA& name_data = name_struct.name; | 238 const CSSM_DATA& name_data = name_struct.name; |
| 238 std::string value = | 239 std::string value = std::string( |
| 239 std::string(reinterpret_cast<std::string::value_type*> | 240 reinterpret_cast<const char*>(name_data.Data), |
| 240 (name_data.Data), | 241 name_data.Length); |
| 241 name_data.Length); | |
| 242 result->push_back(value); | 242 result->push_back(value); |
| 243 } | 243 } |
| 244 } | 244 } |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 } | 247 } |
| 248 | 248 |
| 249 void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle, | 249 void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle, |
| 250 CSSM_OID oid, Time* result) { | 250 CSSM_OID oid, Time* result) { |
| 251 *result = Time::Time(); | 251 *result = Time::Time(); |
| 252 | 252 |
| 253 CSSMFields fields; | 253 CSSMFields fields; |
| 254 OSStatus status = GetCertFields(cert_handle, &fields); | 254 OSStatus status = GetCertFields(cert_handle, &fields); |
| 255 if (status) | 255 if (status) |
| 256 return; | 256 return; |
| 257 | 257 |
| 258 for (size_t field = 0; field < fields.num_of_fields; ++field) { | 258 for (size_t field = 0; field < fields.num_of_fields; ++field) { |
| 259 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { | 259 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { |
| 260 CSSM_X509_TIME* x509_time = | 260 CSSM_X509_TIME* x509_time = reinterpret_cast<CSSM_X509_TIME*>( |
| 261 reinterpret_cast<CSSM_X509_TIME *> | 261 fields.fields[field].FieldValue.Data); |
| 262 (fields.fields[field].FieldValue.Data); | 262 if (x509_time->timeType != BER_TAG_UTC_TIME && |
| 263 std::string time_string = | 263 x509_time->timeType != BER_TAG_GENERALIZED_TIME) { |
| 264 std::string(reinterpret_cast<std::string::value_type*> | 264 LOG(ERROR) << "Unsupported date/time format " |
| 265 (x509_time->time.Data), | 265 << x509_time->timeType; |
| 266 x509_time->time.Length); | |
| 267 | |
| 268 DCHECK(x509_time->timeType == BER_TAG_UTC_TIME || | |
| 269 x509_time->timeType == BER_TAG_GENERALIZED_TIME); | |
| 270 | |
| 271 struct tm time; | |
| 272 const char* parse_string; | |
| 273 if (x509_time->timeType == BER_TAG_UTC_TIME) | |
| 274 parse_string = "%y%m%d%H%M%SZ"; | |
| 275 else if (x509_time->timeType == BER_TAG_GENERALIZED_TIME) | |
| 276 parse_string = "%y%m%d%H%M%SZ"; | |
| 277 else { | |
| 278 // Those are the only two BER tags for time; if neither are used then | |
| 279 // this is a rather broken cert. | |
| 280 return; | 266 return; |
| 281 } | 267 } |
| 282 | 268 |
| 283 strptime(time_string.c_str(), parse_string, &time); | 269 base::StringPiece time_string( |
| 284 | 270 reinterpret_cast<const char*>(x509_time->time.Data), |
| 285 Time::Exploded exploded; | 271 x509_time->time.Length); |
| 286 exploded.year = time.tm_year + 1900; | 272 CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ? |
| 287 exploded.month = time.tm_mon + 1; | 273 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; |
| 288 exploded.day_of_week = time.tm_wday; | 274 if (!ParseCertificateDate(time_string, format, result)) |
| 289 exploded.day_of_month = time.tm_mday; | 275 LOG(ERROR) << "Invalid certificate date/time " << time_string; |
| 290 exploded.hour = time.tm_hour; | 276 return; |
| 291 exploded.minute = time.tm_min; | |
| 292 exploded.second = time.tm_sec; | |
| 293 exploded.millisecond = 0; | |
| 294 | |
| 295 *result = Time::FromUTCExploded(exploded); | |
| 296 break; | |
| 297 } | 277 } |
| 298 } | 278 } |
| 299 } | 279 } |
| 300 | 280 |
| 301 // Creates a SecPolicyRef for the given OID, with optional value. | 281 // Creates a SecPolicyRef for the given OID, with optional value. |
| 302 OSStatus CreatePolicy(const CSSM_OID* policy_OID, | 282 OSStatus CreatePolicy(const CSSM_OID* policy_OID, |
| 303 void* option_data, | 283 void* option_data, |
| 304 size_t option_length, | 284 size_t option_length, |
| 305 SecPolicyRef* policy) { | 285 SecPolicyRef* policy) { |
| 306 SecPolicySearchRef search; | 286 SecPolicySearchRef search; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 327 return noErr; | 307 return noErr; |
| 328 } | 308 } |
| 329 | 309 |
| 330 // Gets the issuer for a given cert, starting with the cert itself and | 310 // Gets the issuer for a given cert, starting with the cert itself and |
| 331 // including the intermediate and finally root certificates (if any). | 311 // including the intermediate and finally root certificates (if any). |
| 332 // This function calls SecTrust but doesn't actually pay attention to the trust | 312 // This function calls SecTrust but doesn't actually pay attention to the trust |
| 333 // result: it shouldn't be used to determine trust, just to traverse the chain. | 313 // result: it shouldn't be used to determine trust, just to traverse the chain. |
| 334 // Caller is responsible for releasing the value stored into *out_cert_chain. | 314 // Caller is responsible for releasing the value stored into *out_cert_chain. |
| 335 OSStatus CopyCertChain(SecCertificateRef cert_handle, | 315 OSStatus CopyCertChain(SecCertificateRef cert_handle, |
| 336 CFArrayRef* out_cert_chain) { | 316 CFArrayRef* out_cert_chain) { |
| 337 DCHECK(cert_handle && out_cert_chain); | 317 DCHECK(cert_handle); |
| 318 DCHECK(out_cert_chain); |
| 338 // Create an SSL policy ref configured for client cert evaluation. | 319 // Create an SSL policy ref configured for client cert evaluation. |
| 339 SecPolicyRef ssl_policy; | 320 SecPolicyRef ssl_policy; |
| 340 OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy); | 321 OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy); |
| 341 if (result) | 322 if (result) |
| 342 return result; | 323 return result; |
| 343 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | 324 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); |
| 344 | 325 |
| 345 // Create a SecTrustRef. | 326 // Create a SecTrustRef. |
| 346 ScopedCFTypeRef<CFArrayRef> input_certs( | 327 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( |
| 347 CFArrayCreate(NULL, (const void**)&cert_handle, 1, | 328 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), |
| 348 &kCFTypeArrayCallBacks)); | 329 1, &kCFTypeArrayCallBacks)); |
| 349 SecTrustRef trust_ref = NULL; | 330 SecTrustRef trust_ref = NULL; |
| 350 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); | 331 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); |
| 351 if (result) | 332 if (result) |
| 352 return result; | 333 return result; |
| 353 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); | 334 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); |
| 354 | 335 |
| 355 // Evaluate trust, which creates the cert chain. | 336 // Evaluate trust, which creates the cert chain. |
| 356 SecTrustResultType status; | 337 SecTrustResultType status; |
| 357 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; | 338 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; |
| 358 result = SecTrustEvaluate(trust, &status); | 339 result = SecTrustEvaluate(trust, &status); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 } | 374 } |
| 394 | 375 |
| 395 // Parses |data| of length |length|, attempting to decode it as the specified | 376 // Parses |data| of length |length|, attempting to decode it as the specified |
| 396 // |format|. If |data| is in the specified format, any certificates contained | 377 // |format|. If |data| is in the specified format, any certificates contained |
| 397 // within are stored into |output|. | 378 // within are stored into |output|. |
| 398 void AddCertificatesFromBytes(const char* data, size_t length, | 379 void AddCertificatesFromBytes(const char* data, size_t length, |
| 399 SecExternalFormat format, | 380 SecExternalFormat format, |
| 400 X509Certificate::OSCertHandles* output) { | 381 X509Certificate::OSCertHandles* output) { |
| 401 SecExternalFormat input_format = format; | 382 SecExternalFormat input_format = format; |
| 402 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( | 383 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( |
| 403 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), | 384 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, |
| 404 length, kCFAllocatorNull)); | 385 kCFAllocatorNull)); |
| 405 | 386 |
| 406 CFArrayRef items = NULL; | 387 CFArrayRef items = NULL; |
| 407 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, | 388 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, |
| 408 NULL, 0, NULL, NULL, &items); | 389 NULL, 0, NULL, NULL, &items); |
| 409 if (status) { | 390 if (status) { |
| 410 DLOG(WARNING) << status << " Unable to import items from data of length " | 391 DLOG(WARNING) << status << " Unable to import items from data of length " |
| 411 << length; | 392 << length; |
| 412 return; | 393 return; |
| 413 } | 394 } |
| 414 | 395 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 445 | 426 |
| 446 } // namespace | 427 } // namespace |
| 447 | 428 |
| 448 void SetMacTestCertificate(X509Certificate* cert) { | 429 void SetMacTestCertificate(X509Certificate* cert) { |
| 449 g_mac_trusted_certificates.Get().SetTestCertificate(cert); | 430 g_mac_trusted_certificates.Get().SetTestCertificate(cert); |
| 450 } | 431 } |
| 451 | 432 |
| 452 void X509Certificate::Initialize() { | 433 void X509Certificate::Initialize() { |
| 453 const CSSM_X509_NAME* name; | 434 const CSSM_X509_NAME* name; |
| 454 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); | 435 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); |
| 455 if (!status) { | 436 if (!status) |
| 456 subject_.Parse(name); | 437 subject_.Parse(name); |
| 457 } | 438 |
| 458 status = SecCertificateGetIssuer(cert_handle_, &name); | 439 status = SecCertificateGetIssuer(cert_handle_, &name); |
| 459 if (!status) { | 440 if (!status) |
| 460 issuer_.Parse(name); | 441 issuer_.Parse(name); |
| 461 } | |
| 462 | 442 |
| 463 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore, | 443 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore, |
| 464 &valid_start_); | 444 &valid_start_); |
| 465 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, | 445 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, |
| 466 &valid_expiry_); | 446 &valid_expiry_); |
| 467 | 447 |
| 468 fingerprint_ = CalculateFingerprint(cert_handle_); | 448 fingerprint_ = CalculateFingerprint(cert_handle_); |
| 469 } | 449 } |
| 470 | 450 |
| 471 // static | 451 // static |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; | 632 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; |
| 653 for (uint32 status_code_index = 0; | 633 for (uint32 status_code_index = 0; |
| 654 status_code_index < chain_info[index].NumStatusCodes; | 634 status_code_index < chain_info[index].NumStatusCodes; |
| 655 ++status_code_index) { | 635 ++status_code_index) { |
| 656 got_certificate_error = true; | 636 got_certificate_error = true; |
| 657 int cert_status = CertStatusFromOSStatus( | 637 int cert_status = CertStatusFromOSStatus( |
| 658 chain_info[index].StatusCodes[status_code_index]); | 638 chain_info[index].StatusCodes[status_code_index]); |
| 659 if (cert_status == CERT_STATUS_COMMON_NAME_INVALID) { | 639 if (cert_status == CERT_STATUS_COMMON_NAME_INVALID) { |
| 660 std::vector<std::string> names; | 640 std::vector<std::string> names; |
| 661 GetDNSNames(&names); | 641 GetDNSNames(&names); |
| 662 if (OverrideHostnameMismatch(hostname, &names)) { | 642 if (OverrideHostnameMismatch(hostname, &names)) |
| 663 cert_status = 0; | 643 cert_status = 0; |
| 664 } | |
| 665 } | 644 } |
| 666 verify_result->cert_status |= cert_status; | 645 verify_result->cert_status |= cert_status; |
| 667 } | 646 } |
| 668 } | 647 } |
| 669 // Be paranoid and ensure that we recorded at least one certificate | 648 // Be paranoid and ensure that we recorded at least one certificate |
| 670 // status on receiving kSecTrustResultRecoverableTrustFailure. The | 649 // status on receiving kSecTrustResultRecoverableTrustFailure. The |
| 671 // call to SecTrustGetCssmResultCode() should pick up when the chain | 650 // call to SecTrustGetCssmResultCode() should pick up when the chain |
| 672 // is not trusted and the loop through CSSM_TP_APPLE_EVIDENCE_INFO | 651 // is not trusted and the loop through CSSM_TP_APPLE_EVIDENCE_INFO |
| 673 // should pick up everything else, but let's be safe. | 652 // should pick up everything else, but let's be safe. |
| 674 if (!verify_result->cert_status && !got_certificate_error) { | 653 if (!verify_result->cert_status && !got_certificate_error) { |
| 675 verify_result->cert_status |= CERT_STATUS_INVALID; | 654 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 676 NOTREACHED(); | 655 NOTREACHED(); |
| 677 } | 656 } |
| 678 break; | 657 break; |
| 679 | 658 |
| 680 default: | 659 default: |
| 681 status = SecTrustGetCssmResultCode(trust_ref, &cssm_result); | 660 status = SecTrustGetCssmResultCode(trust_ref, &cssm_result); |
| 682 if (status) | 661 if (status) |
| 683 return NetErrorFromOSStatus(status); | 662 return NetErrorFromOSStatus(status); |
| 684 verify_result->cert_status |= CertStatusFromOSStatus(cssm_result); | 663 verify_result->cert_status |= CertStatusFromOSStatus(cssm_result); |
| 685 if (!verify_result->cert_status) { | 664 if (!verify_result->cert_status) |
| 686 verify_result->cert_status |= CERT_STATUS_INVALID; | 665 verify_result->cert_status |= CERT_STATUS_INVALID; |
| 687 } | |
| 688 break; | 666 break; |
| 689 } | 667 } |
| 690 | 668 |
| 691 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be | 669 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be |
| 692 // compatible with Windows, which in turn implements this behavior to be | 670 // compatible with Windows, which in turn implements this behavior to be |
| 693 // compatible with WinHTTP, which doesn't report this error (bug 3004). | 671 // compatible with WinHTTP, which doesn't report this error (bug 3004). |
| 694 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; | 672 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; |
| 695 | 673 |
| 696 if (IsCertStatusError(verify_result->cert_status)) | 674 if (IsCertStatusError(verify_result->cert_status)) |
| 697 return MapCertStatusToNetError(verify_result->cert_status); | 675 return MapCertStatusToNetError(verify_result->cert_status); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 SHA1Fingerprint X509Certificate::CalculateFingerprint( | 789 SHA1Fingerprint X509Certificate::CalculateFingerprint( |
| 812 OSCertHandle cert) { | 790 OSCertHandle cert) { |
| 813 SHA1Fingerprint sha1; | 791 SHA1Fingerprint sha1; |
| 814 memset(sha1.data, 0, sizeof(sha1.data)); | 792 memset(sha1.data, 0, sizeof(sha1.data)); |
| 815 | 793 |
| 816 CSSM_DATA cert_data; | 794 CSSM_DATA cert_data; |
| 817 OSStatus status = SecCertificateGetData(cert, &cert_data); | 795 OSStatus status = SecCertificateGetData(cert, &cert_data); |
| 818 if (status) | 796 if (status) |
| 819 return sha1; | 797 return sha1; |
| 820 | 798 |
| 821 DCHECK(NULL != cert_data.Data); | 799 DCHECK(cert_data.Data); |
| 822 DCHECK(0 != cert_data.Length); | 800 DCHECK_NE(cert_data.Length, 0U); |
| 823 | 801 |
| 824 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); | 802 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); |
| 825 | 803 |
| 826 return sha1; | 804 return sha1; |
| 827 } | 805 } |
| 828 | 806 |
| 829 bool X509Certificate::SupportsSSLClientAuth() const { | 807 bool X509Certificate::SupportsSSLClientAuth() const { |
| 830 CSSMFields fields; | 808 CSSMFields fields; |
| 831 if (GetCertFields(cert_handle_, &fields) != noErr) | 809 if (GetCertFields(cert_handle_, &fields) != noErr) |
| 832 return false; | 810 return false; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 863 return false; | 841 return false; |
| 864 return true; | 842 return true; |
| 865 } | 843 } |
| 866 | 844 |
| 867 bool X509Certificate::IsIssuedBy( | 845 bool X509Certificate::IsIssuedBy( |
| 868 const std::vector<CertPrincipal>& valid_issuers) { | 846 const std::vector<CertPrincipal>& valid_issuers) { |
| 869 // Get the cert's issuer chain. | 847 // Get the cert's issuer chain. |
| 870 CFArrayRef cert_chain = NULL; | 848 CFArrayRef cert_chain = NULL; |
| 871 OSStatus result; | 849 OSStatus result; |
| 872 result = CopyCertChain(os_cert_handle(), &cert_chain); | 850 result = CopyCertChain(os_cert_handle(), &cert_chain); |
| 873 if (result != noErr) | 851 if (result) |
| 874 return false; | 852 return false; |
| 875 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); | 853 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); |
| 876 | 854 |
| 877 // Check all the certs in the chain for a match. | 855 // Check all the certs in the chain for a match. |
| 878 int n = CFArrayGetCount(cert_chain); | 856 int n = CFArrayGetCount(cert_chain); |
| 879 for (int i = 0; i < n; ++i) { | 857 for (int i = 0; i < n; ++i) { |
| 880 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>( | 858 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>( |
| 881 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); | 859 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); |
| 882 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( | 860 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( |
| 883 cert_handle, | 861 cert_handle, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 899 NULL, | 877 NULL, |
| 900 CSSM_APPLE_TP_SSL_CLIENT | 878 CSSM_APPLE_TP_SSL_CLIENT |
| 901 }; | 879 }; |
| 902 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, | 880 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, |
| 903 &tp_ssl_options, | 881 &tp_ssl_options, |
| 904 sizeof(tp_ssl_options), | 882 sizeof(tp_ssl_options), |
| 905 out_policy); | 883 out_policy); |
| 906 } | 884 } |
| 907 | 885 |
| 908 // static | 886 // static |
| 909 bool X509Certificate::GetSSLClientCertificates ( | 887 bool X509Certificate::GetSSLClientCertificates( |
| 910 const std::string& server_domain, | 888 const std::string& server_domain, |
| 911 const std::vector<CertPrincipal>& valid_issuers, | 889 const std::vector<CertPrincipal>& valid_issuers, |
| 912 std::vector<scoped_refptr<X509Certificate> >* certs) { | 890 CertificateList* certs) { |
| 913 ScopedCFTypeRef<SecIdentityRef> preferred_identity; | 891 ScopedCFTypeRef<SecIdentityRef> preferred_identity; |
| 914 if (!server_domain.empty()) { | 892 if (!server_domain.empty()) { |
| 915 // See if there's an identity preference for this domain: | 893 // See if there's an identity preference for this domain: |
| 916 ScopedCFTypeRef<CFStringRef> domain_str( | 894 ScopedCFTypeRef<CFStringRef> domain_str( |
| 917 base::SysUTF8ToCFStringRef("https://" + server_domain)); | 895 base::SysUTF8ToCFStringRef("https://" + server_domain)); |
| 918 SecIdentityRef identity = NULL; | 896 SecIdentityRef identity = NULL; |
| 919 if (SecIdentityCopyPreference(domain_str, | 897 // While SecIdentityCopyPreferences appears to take a list of CA issuers |
| 920 0, | 898 // to restrict the identity search to, within Security.framework the |
| 921 NULL, // validIssuers argument is ignored :( | 899 // argument is ignored and filtering unimplemented. See |
| 922 &identity) == noErr) | 900 // SecIdentity.cpp in libsecurity_keychain, specifically |
| 901 // _SecIdentityCopyPreferenceMatchingName(). |
| 902 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr) |
| 923 preferred_identity.reset(identity); | 903 preferred_identity.reset(identity); |
| 924 } | 904 } |
| 925 | 905 |
| 926 // Now enumerate the identities in the available keychains. | 906 // Now enumerate the identities in the available keychains. |
| 927 SecIdentitySearchRef search = nil; | 907 SecIdentitySearchRef search = nil; |
| 928 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); | 908 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); |
| 929 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); | 909 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); |
| 930 while (!err) { | 910 while (!err) { |
| 931 SecIdentityRef identity = NULL; | 911 SecIdentityRef identity = NULL; |
| 932 err = SecIdentitySearchCopyNext(search, &identity); | 912 err = SecIdentitySearchCopyNext(search, &identity); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 if (result) { | 970 if (result) { |
| 991 LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result; | 971 LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result; |
| 992 return NULL; | 972 return NULL; |
| 993 } | 973 } |
| 994 ScopedCFTypeRef<CFMutableArrayRef> chain( | 974 ScopedCFTypeRef<CFMutableArrayRef> chain( |
| 995 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); | 975 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); |
| 996 CFArrayAppendValue(chain, identity); | 976 CFArrayAppendValue(chain, identity); |
| 997 | 977 |
| 998 CFArrayRef cert_chain = NULL; | 978 CFArrayRef cert_chain = NULL; |
| 999 result = CopyCertChain(cert_handle_, &cert_chain); | 979 result = CopyCertChain(cert_handle_, &cert_chain); |
| 1000 if (result) | 980 if (result) { |
| 1001 goto exit; | 981 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; |
| 982 return chain.release(); |
| 983 } |
| 1002 | 984 |
| 1003 // Append the intermediate certs from SecTrust to the result array: | 985 // Append the intermediate certs from SecTrust to the result array: |
| 1004 if (cert_chain) { | 986 if (cert_chain) { |
| 1005 int chain_count = CFArrayGetCount(cert_chain); | 987 int chain_count = CFArrayGetCount(cert_chain); |
| 1006 if (chain_count > 1) { | 988 if (chain_count > 1) { |
| 1007 CFArrayAppendArray(chain, | 989 CFArrayAppendArray(chain, |
| 1008 cert_chain, | 990 cert_chain, |
| 1009 CFRangeMake(1, chain_count - 1)); | 991 CFRangeMake(1, chain_count - 1)); |
| 1010 } | 992 } |
| 1011 CFRelease(cert_chain); | 993 CFRelease(cert_chain); |
| 1012 } | 994 } |
| 1013 exit: | 995 |
| 1014 if (result) | |
| 1015 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; | |
| 1016 return chain.release(); | 996 return chain.release(); |
| 1017 } | 997 } |
| 1018 | 998 |
| 1019 } // namespace net | 999 } // namespace net |
| OLD | NEW |