From 51ddcaf5b16ae39db18c5d4b840ee5ab43ab6b2f Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Fri, 17 May 2013 01:30:34 +0200 Subject: [PATCH] AppleTLS: Properly support Snow Leopard (10.6) Tested on 10.6.8 + XCode 4.2 (llvm-gcc-4.2, clang) --- src/AppleTLSContext.cc | 76 +++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/src/AppleTLSContext.cc b/src/AppleTLSContext.cc index 3f011ebd..939caa39 100644 --- a/src/AppleTLSContext.cc +++ b/src/AppleTLSContext.cc @@ -48,12 +48,15 @@ namespace { using namespace aria2; #if defined(__MAC_10_6) + +#if defined(__MAC_10_7) static const void *query_keys[] = { kSecClass, kSecReturnRef, kSecMatchPolicy, kSecMatchLimit }; +#endif // defined(__MAC_10_7) class cfrelease { const void *ptr_; @@ -112,6 +115,31 @@ namespace { return rv; } + bool checkIdentity(const SecIdentityRef id, const std::string& fingerPrint, + const std::vector supported) + { + SecCertificateRef ref = 0; + if (SecIdentityCopyCertificate(id, &ref) != errSecSuccess) { + A2_LOG_ERROR("Failed to get a certref!"); + return false; + } + cfrelease del_ref(ref); + CFDataRef data = SecCertificateCopyData(ref); + if (!data) { + A2_LOG_ERROR("Failed to get a data!"); + return false; + } + cfrelease del_data(data); + + // Do try all supported hash algorithms. + // Usually the fingerprint would be sha1 or md5, however this is more + // future-proof. Also "usually" doesn't cut it; there is already software + // using SHA-2 class algos, and SHA-3 is standardized and potential users + // cannot be far. + return std::find_if(supported.begin(), supported.end(), + hash_finder(data, fingerPrint)) != supported.end(); + } + #endif // defined(__MAC_10_6) } @@ -166,7 +194,7 @@ bool AppleTLSContext::tryAsFingerprint(const std::string& fingerprint) return false; } -#if defined(__MAC_10_6) +#if defined(__MAC_10_7) A2_LOG_DEBUG(fmt("Looking for cert with fingerprint %s", fp.c_str())); // Build and run the KeyChain the query. @@ -204,25 +232,7 @@ bool AppleTLSContext::tryAsFingerprint(const std::string& fingerprint) A2_LOG_ERROR("Failed to get a value!"); continue; } - SecCertificateRef ref = 0; - if (SecIdentityCopyCertificate(id, &ref) != errSecSuccess) { - A2_LOG_ERROR("Failed to get a certref!"); - continue; - } - cfrelease del_ref(ref); - CFDataRef data = SecCertificateCopyData(ref); - if (!data) { - A2_LOG_ERROR("Failed to get a data!"); - continue; - } - cfrelease del_data(data); - - // Do try all supported hash algorithms. - // Usually the fingerprint would be sha1 or md5, however this is more - // future-proof. Also "usually" doesn't cut it; there is already software - // using SHA-2 class algos, and SHA-3 is standardized and potential users - // cannot be far. - if (std::find_if(ht.begin(), ht.end(), hash_finder(data, fp)) == ht.end()) { + if (!checkIdentity(id, fp, ht)) { continue; } A2_LOG_INFO("Found cert with matching fingerprint"); @@ -234,12 +244,38 @@ bool AppleTLSContext::tryAsFingerprint(const std::string& fingerprint) A2_LOG_ERROR(fmt("Failed to lookup %s in your KeyChain", fingerprint.c_str())); return false; +#else // defined(__MAC_10_7) +#if defined(__MAC_10_6) + + SecIdentitySearchRef search; + + // Deprecated as of 10.7 + OSStatus err = SecIdentitySearchCreate(0, CSSM_KEYUSE_SIGN, &search); + if (err != errSecSuccess) { + A2_LOG_ERROR("Certificate search failed: " + errToString(err)); + } + cfrelease del_search(search); + + SecIdentityRef id; + while (SecIdentitySearchCopyNext(search, &id) == errSecSuccess) { + if (!checkIdentity(id, fp, ht)) { + continue; + } + A2_LOG_INFO("Found cert with matching fingerprint"); + credentials_ = id; + return true; + } + + A2_LOG_ERROR(fmt("Failed to lookup %s in your KeyChain", fingerprint.c_str())); + return false; + #else // defined(__MAC_10_6) A2_LOG_ERROR("Your system does not support creditials via fingerprints; Upgrade to OSX 10.6 or later"); return false; #endif // defined(__MAC_10_6) +#endif // defined(__MAC_10_7) } } // namespace aria2