Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 err = SecPolicySetValue(*policy, &options_data); | 282 err = SecPolicySetValue(*policy, &options_data); |
| 283 if (err) { | 283 if (err) { |
| 284 CFRelease(*policy); | 284 CFRelease(*policy); |
| 285 return err; | 285 return err; |
| 286 } | 286 } |
| 287 } | 287 } |
| 288 return noErr; | 288 return noErr; |
| 289 } | 289 } |
| 290 | 290 |
| 291 // Creates a series of SecPolicyRefs to be added to a SecTrustRef used to | 291 // Creates a series of SecPolicyRefs to be added to a SecTrustRef used to |
| 292 // validate a certificate for an SSL peer. |hostname| contains the name of | 292 // validate a certificate for an SSL server. |hostname| contains the name of |
| 293 // the SSL peer that the certificate should be verified against. |flags| is | 293 // the SSL server that the certificate should be verified against. |flags| is |
| 294 // a bitwise-OR of VerifyFlags that can further alter how trust is | 294 // a bitwise-OR of VerifyFlags that can further alter how trust is |
| 295 // validated, such as how revocation is checked. If successful, returns | 295 // validated, such as how revocation is checked. If successful, returns |
| 296 // noErr, and stores the resultant array of SecPolicyRefs in |policies|. | 296 // noErr, and stores the resultant array of SecPolicyRefs in |policies|. |
| 297 OSStatus CreateTrustPolicies(const std::string& hostname, int flags, | 297 OSStatus CreateTrustPolicies(const std::string& hostname, int flags, |
| 298 ScopedCFTypeRef<CFArrayRef>* policies) { | 298 ScopedCFTypeRef<CFArrayRef>* policies) { |
| 299 CFMutableArrayRef local_policies = | |
| 300 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); | |
| 301 if (!local_policies) | |
| 302 return memFullErr; | |
| 303 ScopedCFTypeRef<CFMutableArrayRef> scoped_local_policies(local_policies); | |
|
wtc
2011/04/21 22:04:38
Please rewrite this as:
ScopedCFTypeRef<CFMutabl
| |
| 304 | |
| 299 // Create an SSL SecPolicyRef, and configure it to perform hostname | 305 // Create an SSL SecPolicyRef, and configure it to perform hostname |
| 300 // validation. The hostname check does 99% of what we want, with the | 306 // validation. The hostname check does 99% of what we want, with the |
| 301 // exception of dotted IPv4 addreses, which we handle ourselves below. | 307 // exception of dotted IPv4 addreses, which we handle ourselves below. |
| 302 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { | 308 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { |
| 303 CSSM_APPLE_TP_SSL_OPTS_VERSION, | 309 CSSM_APPLE_TP_SSL_OPTS_VERSION, |
| 304 hostname.size(), | 310 hostname.size(), |
| 305 hostname.data(), | 311 hostname.data(), |
| 306 0 | 312 0 |
| 307 }; | 313 }; |
| 308 SecPolicyRef ssl_policy; | 314 SecPolicyRef ssl_policy; |
| 309 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options, | 315 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options, |
| 310 sizeof(tp_ssl_options), &ssl_policy); | 316 sizeof(tp_ssl_options), &ssl_policy); |
| 311 if (status) | 317 if (status) |
| 312 return status; | 318 return status; |
| 313 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | 319 CFArrayAppendValue(scoped_local_policies, ssl_policy); |
| 320 CFRelease(ssl_policy); | |
| 314 | 321 |
| 315 // Manually add OCSP and CRL policies. If neither an OCSP or CRL policy is | 322 // Manually add revocation policies. If no revocation policy is specified, |
| 316 // specified, the Apple TP module will add whatever the system settings | 323 // the Apple TP module will add whatever the system settings are, which is |
| 317 // are, which is not desirable here. | 324 // not desirable here. |
|
wtc
2011/04/21 22:04:38
It would be nice to stress that we need to specify
Ryan Sleevi
2011/04/21 23:59:17
Wording has been updated.
| |
| 318 // | |
| 319 // Note that this causes any locally configured OCSP responder URL to be | |
| 320 // ignored. | |
| 321 CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options; | 325 CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options; |
| 322 memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options)); | 326 memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options)); |
| 323 tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; | 327 tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; |
| 324 | 328 |
| 325 CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; | |
| 326 memset(&tp_crl_options, 0, sizeof(tp_crl_options)); | |
| 327 tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; | |
| 328 | |
| 329 if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { | 329 if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { |
| 330 // If an OCSP responder is available, use it, and avoid fetching any | 330 // If an OCSP responder is available, use it, and avoid fetching any |
| 331 // CRLs for that certificate if possible, as they may be much larger. | 331 // CRLs for that certificate if possible, as they may be much larger. |
| 332 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; | 332 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; |
| 333 // Ensure that CRLs can be fetched if a crlDistributionPoint extension | |
| 334 // is found. Otherwise, only the local CRL cache will be consulted. | |
| 335 tp_crl_options.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; | |
| 336 } else { | 333 } else { |
| 337 // Disable OCSP network fetching, but still permit cached OCSP responses | 334 // If the Apple TP believes the certificate being verified may be an EV |
| 338 // to be used. This is equivalent to the Windows code's usage of | 335 // certificate, it will attempt to force OCSP checking. In order to |
| 339 // CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY. | 336 // reliably disable revocation checking, disable access to both the |
| 340 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET; | 337 // network and the cache. Note that when this happens, the Apple TP will |
| 341 // The default CrlFlags will ensure only cached CRLs are used. | 338 // report an error error that OCSP was unavailable, but this will be |
|
wtc
2011/04/21 22:04:38
Typo: error error => error
| |
| 339 // handled and suppressed in X509Certificate::Verify(). | |
| 340 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET | | |
| 341 CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE; | |
| 342 } | 342 } |
| 343 | 343 |
| 344 SecPolicyRef ocsp_policy; | 344 SecPolicyRef ocsp_policy; |
| 345 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options, | 345 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options, |
| 346 sizeof(tp_ocsp_options), &ocsp_policy); | 346 sizeof(tp_ocsp_options), &ocsp_policy); |
| 347 if (status) | 347 if (status) |
| 348 return status; | 348 return status; |
| 349 ScopedCFTypeRef<SecPolicyRef> scoped_ocsp_policy(ocsp_policy); | 349 CFArrayAppendValue(scoped_local_policies, ocsp_policy); |
| 350 CFRelease(ocsp_policy); | |
| 351 | |
| 352 if (!(flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED)) { | |
| 353 policies->reset(scoped_local_policies.release()); | |
| 354 return noErr; | |
|
wtc
2011/04/21 22:04:38
Nit: you can put lines 357-370 inside a
if (flag
| |
| 355 } | |
| 356 | |
| 357 CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; | |
| 358 memset(&tp_crl_options, 0, sizeof(tp_crl_options)); | |
| 359 tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; | |
| 360 // Ensure that CRLs can be fetched if a crlDistributionPoint extension | |
| 361 // is found. Otherwise, only the local CRL cache will be consulted. | |
| 362 tp_crl_options.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; | |
| 350 | 363 |
| 351 SecPolicyRef crl_policy; | 364 SecPolicyRef crl_policy; |
| 352 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, | 365 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, |
| 353 sizeof(tp_crl_options), &crl_policy); | 366 sizeof(tp_crl_options), &crl_policy); |
| 354 if (status) | 367 if (status) |
| 355 return status; | 368 return status; |
| 356 ScopedCFTypeRef<SecPolicyRef> scoped_crl_policy(crl_policy); | 369 CFArrayAppendValue(scoped_local_policies, crl_policy); |
| 370 CFRelease(crl_policy); | |
| 357 | 371 |
| 358 CFTypeRef local_policies[] = { ssl_policy, ocsp_policy, crl_policy }; | 372 policies->reset(scoped_local_policies.release()); |
|
wtc
2011/04/21 22:04:38
We can use 'swap' here. Would that be better?
Ryan Sleevi
2011/04/21 23:59:17
We can't. ScopedCFType<CFArrayRef> is a different
| |
| 359 CFArrayRef policy_array = CFArrayCreate(kCFAllocatorDefault, local_policies, | |
| 360 arraysize(local_policies), | |
| 361 &kCFTypeArrayCallBacks); | |
| 362 if (!policy_array) | |
| 363 return memFullErr; | |
| 364 | |
| 365 policies->reset(policy_array); | |
| 366 return noErr; | 373 return noErr; |
| 367 } | 374 } |
| 368 | 375 |
| 369 // Gets the issuer for a given cert, starting with the cert itself and | 376 // Gets the issuer for a given cert, starting with the cert itself and |
| 370 // including the intermediate and finally root certificates (if any). | 377 // including the intermediate and finally root certificates (if any). |
| 371 // This function calls SecTrust but doesn't actually pay attention to the trust | 378 // This function calls SecTrust but doesn't actually pay attention to the trust |
| 372 // result: it shouldn't be used to determine trust, just to traverse the chain. | 379 // result: it shouldn't be used to determine trust, just to traverse the chain. |
| 373 // Caller is responsible for releasing the value stored into *out_cert_chain. | 380 // Caller is responsible for releasing the value stored into *out_cert_chain. |
| 374 OSStatus CopyCertChain(SecCertificateRef cert_handle, | 381 OSStatus CopyCertChain(SecCertificateRef cert_handle, |
| 375 CFArrayRef* out_cert_chain) { | 382 CFArrayRef* out_cert_chain) { |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 // we'll set our own result to include | 856 // we'll set our own result to include |
| 850 // CERT_STATUS_NO_REVOCATION_MECHANISM. If one or both extensions are | 857 // CERT_STATUS_NO_REVOCATION_MECHANISM. If one or both extensions are |
| 851 // present, and a check fails (server unavailable, OCSP retry later, | 858 // present, and a check fails (server unavailable, OCSP retry later, |
| 852 // signature mismatch), then we'll set our own result to include | 859 // signature mismatch), then we'll set our own result to include |
| 853 // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION. | 860 // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION. |
| 854 tp_action_data.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT; | 861 tp_action_data.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT; |
| 855 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 862 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 856 } else { | 863 } else { |
| 857 // EV requires revocation checking. | 864 // EV requires revocation checking. |
| 858 // Note, under the hood, SecTrustEvaluate() will modify the OCSP options | 865 // Note, under the hood, SecTrustEvaluate() will modify the OCSP options |
| 859 // so as to attempt OCSP fetching if it believes a certificate may chain | 866 // so as to attempt OCSP checking if it believes a certificate may chain |
| 860 // to an EV root. However, because network fetches are disabled in | 867 // to an EV root. However, because network fetches are disabled in |
| 861 // CreateTrustPolicies() when revocation checking is disabled, these | 868 // CreateTrustPolicies() when revocation checking is disabled, these |
| 862 // will only go against the local cache. | 869 // will only go against the local cache. |
| 863 flags &= ~VERIFY_EV_CERT; | 870 flags &= ~VERIFY_EV_CERT; |
| 864 } | 871 } |
| 865 | 872 |
| 866 CFDataRef action_data_ref = | 873 CFDataRef action_data_ref = |
| 867 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, | 874 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, |
| 868 reinterpret_cast<UInt8*>(&tp_action_data), | 875 reinterpret_cast<UInt8*>(&tp_action_data), |
| 869 sizeof(tp_action_data), kCFAllocatorNull); | 876 sizeof(tp_action_data), kCFAllocatorNull); |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1336 CSSM_DATA cert_data; | 1343 CSSM_DATA cert_data; |
| 1337 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); | 1344 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); |
| 1338 if (status) | 1345 if (status) |
| 1339 return false; | 1346 return false; |
| 1340 | 1347 |
| 1341 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), | 1348 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), |
| 1342 cert_data.Length); | 1349 cert_data.Length); |
| 1343 } | 1350 } |
| 1344 | 1351 |
| 1345 } // namespace net | 1352 } // namespace net |
| OLD | NEW |