diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2019-02-06 21:49:47 -0600 |
---|---|---|
committer | Sara Golemon <sara.golemon@mongodb.com> | 2019-03-22 17:17:10 +0000 |
commit | 0eecc58363a2173d9a2bc91e9e7dc8665e12bfac (patch) | |
tree | d2021f0b238a8afc50798f0b4ba0f959764f7a9a | |
parent | c1650e3a6df1196f0c2ebf0824d630ace8db0b4e (diff) | |
download | mongo-0eecc58363a2173d9a2bc91e9e7dc8665e12bfac.tar.gz |
SERVER-39217 SecureTransport with Intermediate CA
(cherry picked from commit 987e5fc980b2288371ebd2c133b58466cc646d60)
-rw-r--r-- | jstests/libs/server-intermediate-ca.pem | 69 | ||||
-rwxr-xr-x | jstests/libs/server-intermediate-ca.pem.sh | 33 | ||||
-rw-r--r-- | jstests/ssl/ssl_intermediate_ca.js | 37 | ||||
-rw-r--r-- | src/mongo/util/net/ssl_manager_apple.cpp | 273 |
4 files changed, 328 insertions, 84 deletions
diff --git a/jstests/libs/server-intermediate-ca.pem b/jstests/libs/server-intermediate-ca.pem new file mode 100644 index 00000000000..49177236cdf --- /dev/null +++ b/jstests/libs/server-intermediate-ca.pem @@ -0,0 +1,69 @@ +-----BEGIN CERTIFICATE----- +MIIDeTCCAmECFHw+FnGIXPbuzpqG28urvjff3s2tMA0GCSqGSIb3DQEBCwUAMHUx +CzAJBgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazEWMBQGA1UEBwwNTmV3IFlv +cmsgQ2l0eTEQMA4GA1UECgwHTW9uZ29EQjEPMA0GA1UECwwGS2VybmVsMRgwFgYD +VQQDDA9JbnRlcm1lZGlhdGUgQ0EwHhcNMTkwMjI3MTY0NjExWhcNMjkwMjI0MTY0 +NjExWjB9MQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxFjAUBgNVBAcM +DU5ldyBZb3JrIENpdHkxEDAOBgNVBAoMB01vbmdvREIxDzANBgNVBAsMBktlcm5l +bDEgMB4GA1UEAwwXU2VydmVyIFZpYSBJbnRlcm1lZGlhdGUwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCZ7sGixY2OsOTWzB1Ww08iFToqFxdo7/nqoEX6 +kktPVSKdCCCsx55hWcgR0jwIfuXOQWFvD6b50NTmdxRSGodgcv4hcrGqPbyxxEns +2+hKUaULjgOox9wS8aiSSoQtGXEGlyd06coatOMIbPIG/7Txq8NuzCnznby86wkw +ptO21crMa/Q9B0sFzl8DJaGsMcDjoyzN52eJ7xnzDoyDkzLnJZDlK55m1xB2TpPY +0m+0eg2QUUP9KKkQ0oM4rChBgj3FeUlitiIQo6SS1VtgAgQh8Gecfrk4J9cp+W3Q +PoMZWM62WqVfEG3j4Fe2I5QS3R/8SeYYXcohI97ie5LAn2PTAgMBAAEwDQYJKoZI +hvcNAQELBQADggEBAFl7XxkK25GRW1J/pBYb6VJ3YiZeK5xVVSltIBoUs12Vq5se +BD05opUfQyfB7Y3CwbiSUcFmr+zqrQMPSgT08dRF+1VarRB5q/Pn3uHOPPGgO5uA +ZNzLjMkEwazKCs5R6+7z6INARW8356PQziYCRyMjBTi2vYghDq6Hji4V7w1n+9l2 +DUCPbAdD35NOv62y6SRBtWwV2zQJ8LSB7zRcQCzxz7e3WZSVv/ztP74huYrPeSpK +7oLAwItP+5o4dc6ApsvTspXb+m46+GU6DG4hdAJ6lX+9P96sHWTkR72lBIPVMs32 +RlD1A0yqVwxoFUKwyeMtmS0ZvX1zh9xxVj1wX/o= +-----END CERTIFICATE----- +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAme7BosWNjrDk1swdVsNPIhU6KhcXaO/56qBF+pJLT1UinQgg +rMeeYVnIEdI8CH7lzkFhbw+m+dDU5ncUUhqHYHL+IXKxqj28scRJ7NvoSlGlC44D +qMfcEvGokkqELRlxBpcndOnKGrTjCGzyBv+08avDbswp8528vOsJMKbTttXKzGv0 +PQdLBc5fAyWhrDHA46Mszednie8Z8w6Mg5My5yWQ5SueZtcQdk6T2NJvtHoNkFFD +/SipENKDOKwoQYI9xXlJYrYiEKOkktVbYAIEIfBnnH65OCfXKflt0D6DGVjOtlql +XxBt4+BXtiOUEt0f/EnmGF3KISPe4nuSwJ9j0wIDAQABAoIBADblWtD9uvoEQ9gG +ewASLwpsn42bJpIZ4vq1pb8ypQDpz6pI175Ggkkdh6gzXY16E+J2lpTQ9C9rNkHq +fai6JUVUPSUYjhu0YLLU2bhKxJCchUuVneB3RhjLbd6eDH048YH0LfIX3iegEsdS +cw3j61e0dcHxtZRX0JNfDqv3EtHE5x76Qm7brfTwVt4O3dKKEodR8WKmIBPhJ/UI +vZWym79doEaHXgFdvn5qxRhxDS4Fm2l22x4apSV/mVYFONoV7RrUkKYxB02DPImM +mVtScNdYEI+LWnUJGFVvxpNYLR6IgoiPaGPFtFCH5X746tpW7Nj4eKHpQcIobEGt +yucbz2ECgYEAzTnvHSRXNeQlX3BntDYxYEjgW6RJGPaaSgI1Ggk6rJeO9XKJdUYQ +WfWgugL9GHmdda0V0CJQXyciarw4AXaGDb7IoxYi7lBhgAFYP2WNX5a6lYdQOyds +HKPxIBYjqNqyy4bnq1sBzDKlIdblluBX7H+lh7NIQykuTGveKtpENw8CgYEAwAQf +rZfaqPM8ppABqfkt1/rhvcpq+M+xN0WewLOQSGzXJdoJSnY263iPUYqVLjsjSr4v +cP8aUsLy7GR1vbyVf6BTBtVA556rcnWccpkEern+Ip2SoJX5UJl7+FhIrQsxrUzI +W6Pzurqa4EYLikigX8h31kkF47oz5EiAQ4ZrZv0CgYA5g/YGhcvHN7RdpgP6VoHK +CUKPjGBMFbix6yJ0tId0HVmcYkgxzLwCajtsRjAmbtb5RtPpK+S4diBIJ43Ooyf4 +rDJQuoB5p59bn4Ta55wSYQzToUOUAH1lHXETXAEMbpZTQfClbnD3iG4NKMvZV/Bs +QG3ktRMYd28ZTdXKzrb1cwKBgQCVIN7FgMHHI5pANmnEbA1px6SZNWNdOFkHd1+z +hAIT7cwuzqcWmLdQrAKLLtlr3WwseYb4+HemPVhTtjYnlRZ617aEAQ32lanMLIHE +EwmCk39HvR+K7s+CBKJen5paIu6DDLYzTiNWK+VrN5tw27UKjvRbjb0wP4Zbzt8n +EnfJtQKBgCPfec6SZ1ptZ1Tfhim2j61AnqMvGSm7drOLI5cMsLE92fEhttb21A7u +i1qy9Qkm4HN4DvqNPc8XVkdn3+qn/TAS30V8G/yrpUFJHSLAikKqyadpiTd60dqR +qrt3S81/HL9Mq0NLuFS9stiBDM2hVWB9dXiX2husS09ZZfXmyvvX +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDcDCCAlgCFDUYb355zUYCIVzHyv83FTWWlFDOMA0GCSqGSIb3DQEBCwUAMHQx +FzAVBgNVBAMTDktlcm5lbCBUZXN0IENBMQ8wDQYDVQQLEwZLZXJuZWwxEDAOBgNV +BAoTB01vbmdvREIxFjAUBgNVBAcTDU5ldyBZb3JrIENpdHkxETAPBgNVBAgTCE5l +dyBZb3JrMQswCQYDVQQGEwJVUzAeFw0xOTAyMjcxNjQ2MTFaFw0yOTAyMjQxNjQ2 +MTFaMHUxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhOZXcgWW9yazEWMBQGA1UEBwwN +TmV3IFlvcmsgQ2l0eTEQMA4GA1UECgwHTW9uZ29EQjEPMA0GA1UECwwGS2VybmVs +MRgwFgYDVQQDDA9JbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCojypRgkrYr12fDrPBsVChLHKXaoKVp+vSITmzxvwhu6iORUeF +nZCUxEDGreZrMF30KLtRNXOGrFlgUhxVdZrqt0YM4BFIJFeoYTuEOPrZVEtF6Qi8 +po+6zms8FBAdtk+zLJ4sRfq1Oqdbh/Fl6k53z/zV6ueRkSVZYArrzNwgUynRGvGN +7PF+ivb4qG8qCo9iKcwp2Ie4k346XyTxMOkzcV+kGmAgmfO+yehmS5XFu62tH1ek +V3BGgU2rbQlty40P0f1EVlF0mWyzzZVSIOUnYZruRsYHwXs1hy+l4otfEcBb76Sk +vLHtPC/nXmf6Vamw86FiJkIRGhwmmeYjHeo9AgMBAAEwDQYJKoZIhvcNAQELBQAD +ggEBAGO+3qQVjmwtjnoJY3DnWV15ySBj4b6Ir1LlKfngXfpfwlksOZaQsg0mLv3S +sNfWK1BgQAZZ6iRxIc+T4stpIe3GppDB+a194s7ZuhXP1HpdEZEjr5CkD5cQ5YKv +OgDry6iGeHnUkaATRHR1iXHCnbAWVkKRNObkcL5Haxa1jLlyiHdMJmqwlfVWVOlx +NlpEz/Nw6eVXE6vOfYx5lRCVxzP4Ym1RH8+D/c+xoixEgXpif5PpEeEP4IYm1xkr +nUCpkvESWaAVGnBpeHUs5WuovyvBrvxBSB6sjIvrr45jLMwX0agJ8rx8RzZ9IShA +WyA3ZWFlGiMWYzxi/2B/z+GhIS8= +-----END CERTIFICATE----- diff --git a/jstests/libs/server-intermediate-ca.pem.sh b/jstests/libs/server-intermediate-ca.pem.sh new file mode 100755 index 00000000000..3860ca899b9 --- /dev/null +++ b/jstests/libs/server-intermediate-ca.pem.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Create an intermediate signing authority and use it to sign a server certificate. +# Run this from the base directory of the server source. +set -ev + +PREFIX="/C=US/ST=New York/L=New York City/O=MongoDB/OU=Kernel" +OPENSSL="/opt/mongodbtoolchain/v3/bin/openssl" + +cd jstests/libs + +# Build intermediate CA. +$OPENSSL req -new -subj "${PREFIX}/CN=Intermediate CA" \ + -keyout intermediate-ca.key -out intermediate-ca.csr \ + -nodes -batch -sha256 -newkey rsa:2048 +$OPENSSL rsa -in intermediate-ca.key -out intermediate-ca.rsa +$OPENSSL x509 -in intermediate-ca.csr -out intermediate-ca.pem \ + -req -CA ca.pem -days 3650 -CAcreateserial + +# Build leaf cert signed by intermediate CA. +$OPENSSL req -new -subj "${PREFIX}/CN=Server Via Intermediate" \ + -keyout server-intermediate-ca.key -out server-intermediate-ca.csr \ + -nodes -batch -sha256 -newkey rsa:2048 +$OPENSSL rsa -in server-intermediate-ca.key -out server-intermediate-ca.rsa +$OPENSSL x509 -in server-intermediate-ca.csr -out server-intermediate-ca.pem \ + -req -CA intermediate-ca.pem -CAkey intermediate-ca.rsa \ + -days 3650 -CAcreateserial + +# Create final bundle and cleanup. +cat server-intermediate-ca.rsa intermediate-ca.pem >> server-intermediate-ca.pem + +rm ca.srl intermediate-ca.srl +rm server-intermediate-ca.key server-intermediate-ca.rsa server-intermediate-ca.csr +rm intermediate-ca.pem intermediate-ca.rsa intermediate-ca.key intermediate-ca.csr diff --git a/jstests/ssl/ssl_intermediate_ca.js b/jstests/ssl/ssl_intermediate_ca.js new file mode 100644 index 00000000000..838f43bcb30 --- /dev/null +++ b/jstests/ssl/ssl_intermediate_ca.js @@ -0,0 +1,37 @@ +// Test that including intermediate certificates +// in the certificate key file will be sent to the remote. + +(function() { + 'use strict'; + + load('jstests/ssl/libs/ssl_helpers.js'); + + if (determineSSLProvider() === 'windows') { + // FIXME: SERVER-39574 + print("Skipping test with windows SChannel pending SERVER-39574"); + return; + } + + // server-intermediate-ca was signed by ca.pem, not trusted-ca.pem + const VALID_CA = 'jstests/libs/ca.pem'; + const INVALID_CA = 'jstests/libs/trusted-ca.pem'; + + function runTest(inbound, outbound) { + const mongod = MongoRunner.runMongod({ + sslMode: 'requireSSL', + sslAllowConnectionsWithoutCertificates: '', + sslPEMKeyFile: 'jstests/libs/server-intermediate-ca.pem', + sslCAFile: outbound, + sslClusterCAFile: inbound, + }); + assert(mongod); + assert.eq(mongod.getDB('admin').system.users.find({}).toArray(), []); + MongoRunner.stopMongod(mongod); + } + + // Normal mode, we have a valid CA being presented for outbound and inbound. + runTest(VALID_CA, VALID_CA); + + // Alternate CA mode, only the inbound CA is valid. + runTest(VALID_CA, INVALID_CA); +})(); diff --git a/src/mongo/util/net/ssl_manager_apple.cpp b/src/mongo/util/net/ssl_manager_apple.cpp index 952bbfe9d19..d0b2e9125bf 100644 --- a/src/mongo/util/net/ssl_manager_apple.cpp +++ b/src/mongo/util/net/ssl_manager_apple.cpp @@ -69,6 +69,11 @@ namespace mongo { namespace { +template <typename T> +constexpr T cf_cast(::CFTypeRef val) { + return static_cast<T>(const_cast<void*>(val)); +} + // CFAbsoluteTime and X.509 is relative to Jan 1 2001 00:00:00 GMT // Unix Epoch (and thereby Date_t) is relative to Jan 1, 1970 00:00:00 GMT static const ::CFAbsoluteTime k20010101_000000_GMT = 978307200; @@ -490,6 +495,174 @@ StatusWith<std::vector<std::string>> extractSubjectAlternateNames(::CFDictionary return ret; } +bool isCFDataEqual(::CFDataRef a, ::CFDataRef b) { + const auto len = ::CFDataGetLength(a); + if (::CFDataGetLength(b) != len) { + return false; + } + + const auto* A = ::CFDataGetBytePtr(a); + const auto* B = ::CFDataGetBytePtr(b); + return 0 == memcmp(A, B, len); +} + +/** + * Attempt to merge a security item bundle into an + * identity and optional cert chain. + * + * The file must have exactly one key which will be paired with + * the first available certificate, or exactly one identity. + */ +StatusWith<::CFArrayRef> bindIdentity(::CFArrayRef certs) { + auto count = ::CFArrayGetCount(certs); + if (count == 0) { + return certs; + } + + // Ideal case, exactly one identity. + if (count == 1) { + auto idElem = ::CFArrayGetValueAtIndex(certs, 0); + if (::CFGetTypeID(idElem) == ::SecIdentityGetTypeID()) { + return certs; + } + } + + // Optimistic case, exactly one cert-key pair. + if (count == 2) { + auto certElem = ::CFArrayGetValueAtIndex(certs, 0); + auto keyElem = ::CFArrayGetValueAtIndex(certs, 1); + if (::CFGetTypeID(certElem) == ::SecKeyGetTypeID()) { + std::swap(certElem, keyElem); + } + if ((::CFGetTypeID(certElem) == ::SecCertificateGetTypeID()) && + (::CFGetTypeID(keyElem) == ::SecKeyGetTypeID())) { + CFUniquePtr<::SecIdentityRef> cfid(::SecIdentityCreate( + nullptr, cf_cast<::SecCertificateRef>(certElem), cf_cast<::SecKeyRef>(keyElem))); + if (cfid) { + auto id = static_cast<const void*>(cfid.get()); + return ::CFArrayCreate(nullptr, &id, 1, &kCFTypeArrayCallBacks); + } + } + } + + // Complex case, multiple certs. + // Find the key, pair it with the first cert, and bundle the remaining certs in. + std::vector<::SecCertificateRef> intermediateCerts; + ::SecIdentityRef id = nullptr; + ::SecCertificateRef leafCert = nullptr; + ::SecKeyRef key = nullptr; + for (::CFIndex i = 0; i < count; ++i) { + auto elem = ::CFArrayGetValueAtIndex(certs, i); + invariant(elem); + + const auto elemType = ::CFGetTypeID(elem); + if (elemType == ::SecIdentityGetTypeID()) { + if (id) { + return {ErrorCodes::InvalidSSLConfiguration, + str::stream() << "Multiple identities found in PEM file"}; + } + id = cf_cast<::SecIdentityRef>(elem); + continue; + } + + if (elemType == ::SecKeyGetTypeID()) { + if (key) { + return {ErrorCodes::InvalidSSLConfiguration, + str::stream() << "Multiple private keys found in PEM file"}; + } + key = cf_cast<::SecKeyRef>(elem); + continue; + } + + if (elemType != ::SecCertificateGetTypeID()) { + // Ignore other types. + continue; + } + + if (leafCert) { + intermediateCerts.push_back(cf_cast<::SecCertificateRef>(elem)); + } else { + leafCert = cf_cast<::SecCertificateRef>(elem); + } + } + + if (id && key) { + return {ErrorCodes::InvalidSSLConfiguration, + "Found both identity and private key in PEM file"}; + } + if (key && !leafCert) { + return {ErrorCodes::InvalidSSLConfiguration, "Found key without certificate in PEM file"}; + } + + CFUniquePtr<::CFMutableArrayRef> ret( + ::CFArrayCreateMutable(nullptr, count, &kCFTypeArrayCallBacks)); + + if (id) { + ::CFArrayAppendValue(ret.get(), id); + } + + if (key) { + CFUniquePtr<::SecIdentityRef> ident(::SecIdentityCreate(nullptr, leafCert, key)); + if (!ident) { + return {ErrorCodes::InvalidSSLConfiguration, "Unable to create Identity from keyfile"}; + } + ::CFArrayAppendValue(ret.get(), ident.get()); + } else if (leafCert) { + ::CFArrayAppendValue(ret.get(), leafCert); + } + + for (auto& cert : intermediateCerts) { + ::CFArrayAppendValue(ret.get(), cert); + } + + return ret.release(); +} + +/** + * Strip a security item bundle down to just Certificates. + * This means ignoring SecKeyRef and splitting SecIdentityRef + * into just their SecCertificateRef potions. + */ +StatusWith<::CFArrayRef> stripKeys(::CFArrayRef certs) { + auto count = ::CFArrayGetCount(certs); + + if (count == 0) { + return certs; + } + + // Strip unpaired keys and identities. + CFUniquePtr<::CFMutableArrayRef> ret( + ::CFArrayCreateMutable(nullptr, count, &kCFTypeArrayCallBacks)); + for (::CFIndex i = 0; i < count; ++i) { + auto elem = ::CFArrayGetValueAtIndex(certs, i); + if (!elem) { + continue; + } + const auto type = ::CFGetTypeID(elem); + if (type == ::SecCertificateGetTypeID()) { + // Preserve Certificates. + ::CFArrayAppendValue(ret.get(), elem); + continue; + } + if (type != ::SecIdentityGetTypeID()) { + continue; + } + + // Extract public certificate from Identity. + ::SecCertificateRef cert = nullptr; + const auto status = ::SecIdentityCopyCertificate(cf_cast<::SecIdentityRef>(elem), &cert); + CFUniquePtr<::SecCertificateRef> cfcert(cert); + if (status != ::errSecSuccess) { + return {ErrorCodes::InternalError, + str::stream() << "Unable to extract certificate from identity: " + << stringFromOSStatus(status)}; + } + ::CFArrayAppendValue(ret.get(), cfcert.get()); + } + + return ret.release(); +} + enum LoadPEMMode { kLoadPEMBindIdentities = true, kLoadPEMStripKeys = false, @@ -511,7 +684,8 @@ StatusWith<CFUniquePtr<::CFArrayRef>> loadPEM(const std::string& keyfilepath, const auto retFail = [&keyfilepath, &passphrase](const std::string& msg = "") { return Status(ErrorCodes::InvalidSSLConfiguration, str::stream() << "Unable to load PEM from '" << keyfilepath << "'" - << (passphrase.empty() ? "" : " with passphrase: ") + << (passphrase.empty() ? "" : " with passphrase") + << (msg.empty() ? "" : ": ") << msg); }; @@ -561,89 +735,22 @@ StatusWith<CFUniquePtr<::CFArrayRef>> loadPEM(const std::string& keyfilepath, << stringFromOSStatus(status)); } - auto count = ::CFArrayGetCount(cfcerts.get()); - if ((count > 0) && (mode == kLoadPEMBindIdentities)) { - // Turn Certificate/Key pairs into identities. - CFUniquePtr<::CFMutableArrayRef> bind( - ::CFArrayCreateMutable(nullptr, count, &kCFTypeArrayCallBacks)); - for (::CFIndex i = 0; i < count; ++i) { - auto elem = ::CFArrayGetValueAtIndex(cfcerts.get(), i); - invariant(elem); - const auto type = ::CFGetTypeID(elem); - if (type == ::SecIdentityGetTypeID()) { - // Our import had a proper identity in it, ready to go. - ::CFArrayAppendValue(bind.get(), elem); - continue; - } - if (type != ::SecCertificateGetTypeID()) { - continue; - } - - // Attempt to match the certificate to a private key in the aggregate we just imported. - CFUniquePtr<::SecIdentityRef> cfid; - for (::CFIndex j = 0; j < count; ++j) { - auto key = ::CFArrayGetValueAtIndex(cfcerts.get(), j); - invariant(key); - if (::CFGetTypeID(key) != ::SecKeyGetTypeID()) { - continue; - } - auto id = - ::SecIdentityCreate(nullptr, - static_cast<::SecCertificateRef>(const_cast<void*>(elem)), - static_cast<::SecKeyRef>(const_cast<void*>(key))); - if (id) { - cfid.reset(id); - break; - } - } - if (cfid) { - ::CFArrayAppendValue(bind.get(), cfid.get()); - } else { - ::CFArrayAppendValue(bind.get(), elem); - } + if (mode == kLoadPEMBindIdentities) { + auto swCerts = bindIdentity(cfcerts.get()); + if (!swCerts.isOK()) { + return swCerts.getStatus(); } - // Reencapsulate to allow the inner type to change. - cfcerts.reset(bind.release()); - count = ::CFArrayGetCount(cfcerts.get()); - } - - if ((count > 0) && (mode == kLoadPEMStripKeys)) { - // Strip unpaired keys and identities. - CFUniquePtr<::CFMutableArrayRef> strip( - ::CFArrayCreateMutable(nullptr, count, &kCFTypeArrayCallBacks)); - for (::CFIndex i = 0; i < count; ++i) { - auto elem = ::CFArrayGetValueAtIndex(cfcerts.get(), i); - if (!elem) { - continue; - } - const auto type = ::CFGetTypeID(elem); - if (type == ::SecCertificateGetTypeID()) { - // Preserve Certificates. - ::CFArrayAppendValue(strip.get(), elem); - continue; - } - if (type != ::SecIdentityGetTypeID()) { - continue; - } - - // Extract public certificate from Identity. - ::SecCertificateRef cert = nullptr; - const auto status = ::SecIdentityCopyCertificate( - static_cast<::SecIdentityRef>(const_cast<void*>(elem)), &cert); - CFUniquePtr<::SecCertificateRef> cfcert(cert); - if (status != ::errSecSuccess) { - return {ErrorCodes::InternalError, - str::stream() << "Unable to extract certificate from identity: " - << stringFromOSStatus(status)}; - } - ::CFArrayAppendValue(strip.get(), cfcert.get()); + cfcerts.reset(swCerts.getValue()); + } else { + invariant(mode == kLoadPEMStripKeys); + auto swCerts = stripKeys(cfcerts.get()); + if (!swCerts.isOK()) { + return swCerts.getStatus(); } - // Reencapsulate to allow the inner type to change. - cfcerts.reset(strip.release()); - count = ::CFArrayGetCount(cfcerts.get()); + cfcerts.reset(swCerts.getValue()); } - if (count <= 0) { + if (::CFArrayGetCount(cfcerts.get()) <= 0) { return {ErrorCodes::InvalidSSLConfiguration, str::stream() << "PEM file '" << keyfilepath << "' has no certificates"}; } @@ -710,8 +817,7 @@ StatusWith<SSLX509Name> certificateGetSubject(::CFArrayRef certs, Date_t* expire } ::SecCertificateRef idcert = nullptr; - auto status = ::SecIdentityCopyCertificate( - static_cast<::SecIdentityRef>(const_cast<void*>(root)), &idcert); + auto status = ::SecIdentityCopyCertificate(cf_cast<::SecIdentityRef>(root), &idcert); if (status != ::errSecSuccess) { return {ErrorCodes::InvalidSSLConfiguration, str::stream() << "Unable to get certificate from identity: " @@ -791,8 +897,7 @@ StatusWith<CFUniquePtr<::CFArrayRef>> copyMatchingCertificate( CFUniquePtr<::CFMutableArrayRef> cfresult( ::CFArrayCreateMutable(nullptr, 1, &::kCFTypeArrayCallBacks)); for (::CFIndex i = 0; i < ::CFArrayGetCount(cfident.get()); ++i) { - auto ident = static_cast<::SecIdentityRef>( - const_cast<void*>(::CFArrayGetValueAtIndex(cfident.get(), i))); + auto ident = cf_cast<::SecIdentityRef>(::CFArrayGetValueAtIndex(cfident.get(), i)); if (::CFGetTypeID(ident) != ::SecIdentityGetTypeID()) { continue; } |