AppleTLS: Properly support Snow Leopard (10.6)

Tested on 10.6.8 + XCode 4.2 (llvm-gcc-4.2, clang)
pull/89/head
Nils Maier 2013-05-17 01:30:34 +02:00
parent 0adc4b795e
commit 51ddcaf5b1
1 changed files with 56 additions and 20 deletions

View File

@ -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<std::string> 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