mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8303465: KeyStore of type KeychainStore, provider Apple does not show all trusted certificates
Reviewed-by: mbaesken, weijun
This commit is contained in:
parent
11fb5b2209
commit
ac41c03003
3 changed files with 213 additions and 52 deletions
|
@ -69,7 +69,7 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
Certificate cert;
|
||||
long certRef; // SecCertificateRef for this key
|
||||
|
||||
// Each KeyStore.TrustedCertificateEntry have 2 attributes:
|
||||
// Each KeyStore.TrustedCertificateEntry has 2 attributes:
|
||||
// 1. "trustSettings" -> trustSettings.toString()
|
||||
// 2. "2.16.840.1.113894.746875.1.1" -> trustedKeyUsageValue
|
||||
// The 1st one is mainly for debugging use. The 2nd one is similar
|
||||
|
@ -652,7 +652,6 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
_releaseKeychainItemRef(((TrustedCertEntry)entry).certRef);
|
||||
}
|
||||
} else {
|
||||
Certificate certElem;
|
||||
KeyEntry keyEntry = (KeyEntry)entry;
|
||||
|
||||
if (keyEntry.chain != null) {
|
||||
|
@ -804,8 +803,26 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
tce.cert = cert;
|
||||
tce.certRef = keychainItemRef;
|
||||
|
||||
// Check whether a certificate with same alias already exists and is the same
|
||||
// If yes, we can return here - the existing entry must have the same
|
||||
// properties and trust settings
|
||||
if (entries.contains(alias.toLowerCase())) {
|
||||
int uniqueVal = 1;
|
||||
String originalAlias = alias;
|
||||
var co = entries.get(alias.toLowerCase());
|
||||
while (co != null) {
|
||||
if (co instanceof TrustedCertEntry tco) {
|
||||
if (tco.cert.equals(tce.cert)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
alias = originalAlias + " " + uniqueVal++;
|
||||
co = entries.get(alias.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
tce.trustSettings = new ArrayList<>();
|
||||
Map<String,String> tmpMap = new LinkedHashMap<>();
|
||||
Map<String, String> tmpMap = new LinkedHashMap<>();
|
||||
for (int i = 0; i < inputTrust.size(); i++) {
|
||||
if (inputTrust.get(i) == null) {
|
||||
tce.trustSettings.add(tmpMap);
|
||||
|
@ -828,9 +845,10 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
} catch (Exception e) {
|
||||
isSelfSigned = false;
|
||||
}
|
||||
|
||||
if (tce.trustSettings.isEmpty()) {
|
||||
if (isSelfSigned) {
|
||||
// If a self-signed certificate has an empty trust settings,
|
||||
// If a self-signed certificate has trust settings without specific entries,
|
||||
// trust it for all purposes
|
||||
tce.trustedKeyUsageValue = KnownOIDs.anyExtendedKeyUsage.value();
|
||||
} else {
|
||||
|
@ -843,11 +861,19 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
for (var oneTrust : tce.trustSettings) {
|
||||
var result = oneTrust.get("kSecTrustSettingsResult");
|
||||
// https://developer.apple.com/documentation/security/sectrustsettingsresult?language=objc
|
||||
// 1 = kSecTrustSettingsResultTrustRoot, 2 = kSecTrustSettingsResultTrustAsRoot
|
||||
// 1 = kSecTrustSettingsResultTrustRoot, 2 = kSecTrustSettingsResultTrustAsRoot,
|
||||
// 3 = kSecTrustSettingsResultDeny
|
||||
// If missing, a default value of kSecTrustSettingsResultTrustRoot is assumed
|
||||
// for self-signed certificates (see doc for SecTrustSettingsCopyTrustSettings).
|
||||
// (see doc for SecTrustSettingsCopyTrustSettings).
|
||||
// Note that the same SecPolicyOid can appear in multiple trust settings
|
||||
// for different kSecTrustSettingsAllowedError and/or kSecTrustSettingsPolicyString.
|
||||
|
||||
// If we find explicit distrust in some record, we ignore the certificate
|
||||
if ("3".equals(result)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trust, if explicitly trusted or result is null and certificate is self signed
|
||||
if ((result == null && isSelfSigned)
|
||||
|| "1".equals(result) || "2".equals(result)) {
|
||||
// When no kSecTrustSettingsPolicy, it means everything
|
||||
|
@ -867,20 +893,13 @@ public final class KeychainStore extends KeyStoreSpi {
|
|||
tce.trustedKeyUsageValue = values.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Make a creation date.
|
||||
if (creationDate != 0)
|
||||
tce.date = new Date(creationDate);
|
||||
else
|
||||
tce.date = new Date();
|
||||
|
||||
int uniqueVal = 1;
|
||||
String originalAlias = alias;
|
||||
|
||||
while (entries.containsKey(alias.toLowerCase())) {
|
||||
alias = originalAlias + " " + uniqueVal;
|
||||
uniqueVal++;
|
||||
}
|
||||
|
||||
entries.put(alias.toLowerCase(), tce);
|
||||
} catch (Exception e) {
|
||||
// The certificate will be skipped.
|
||||
|
|
|
@ -381,6 +381,35 @@ errOut:
|
|||
|
||||
#define ADDNULL(list) (*env)->CallBooleanMethod(env, list, jm_listAdd, NULL)
|
||||
|
||||
|
||||
static void addTrustSettingsToInputTrust(JNIEnv *env, jmethodID jm_listAdd, CFArrayRef trustSettings, jobject inputTrust)
|
||||
{
|
||||
CFIndex count = CFArrayGetCount(trustSettings);
|
||||
for (int i = 0; i < count; i++) {
|
||||
CFDictionaryRef oneTrust = (CFDictionaryRef) CFArrayGetValueAtIndex(trustSettings, i);
|
||||
CFIndex size = CFDictionaryGetCount(oneTrust);
|
||||
const void * keys [size];
|
||||
const void * values [size];
|
||||
CFDictionaryGetKeysAndValues(oneTrust, keys, values);
|
||||
for (int j = 0; j < size; j++) {
|
||||
NSString* s = [NSString stringWithFormat:@"%@", keys[j]];
|
||||
ADD(inputTrust, s);
|
||||
s = [NSString stringWithFormat:@"%@", values[j]];
|
||||
ADD(inputTrust, s);
|
||||
}
|
||||
SecPolicyRef certPolicy;
|
||||
certPolicy = (SecPolicyRef)CFDictionaryGetValue(oneTrust, kSecTrustSettingsPolicy);
|
||||
if (certPolicy != NULL) {
|
||||
CFDictionaryRef policyDict = SecPolicyCopyProperties(certPolicy);
|
||||
ADD(inputTrust, @"SecPolicyOid");
|
||||
NSString* s = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(policyDict, @"SecPolicyOid")];
|
||||
ADD(inputTrust, s);
|
||||
CFRelease(policyDict);
|
||||
}
|
||||
ADDNULL(inputTrust);
|
||||
}
|
||||
}
|
||||
|
||||
static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
|
||||
{
|
||||
// Search the user keychain list for all X509 certificates.
|
||||
|
@ -435,47 +464,41 @@ static void addCertificatesToKeystore(JNIEnv *env, jobject keyStore)
|
|||
goto errOut;
|
||||
}
|
||||
|
||||
// Only add certificates with trusted settings
|
||||
CFArrayRef trustSettings;
|
||||
if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainUser, &trustSettings)
|
||||
== errSecItemNotFound) {
|
||||
// See KeychainStore::createTrustedCertEntry for content of inputTrust
|
||||
// We load trust settings from domains kSecTrustSettingsDomainUser and kSecTrustSettingsDomainAdmin
|
||||
// kSecTrustSettingsDomainSystem is ignored because it seems to only contain data for root certificates
|
||||
jobject inputTrust = NULL;
|
||||
CFArrayRef trustSettings = NULL;
|
||||
|
||||
// Load user trustSettings into inputTrust
|
||||
if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainUser, &trustSettings) == errSecSuccess && trustSettings != NULL) {
|
||||
inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
|
||||
if (inputTrust == NULL) {
|
||||
CFRelease(trustSettings);
|
||||
goto errOut;
|
||||
}
|
||||
addTrustSettingsToInputTrust(env, jm_listAdd, trustSettings, inputTrust);
|
||||
CFRelease(trustSettings);
|
||||
}
|
||||
// Load admin trustSettings into inputTrust
|
||||
trustSettings = NULL;
|
||||
if (SecTrustSettingsCopyTrustSettings(certRef, kSecTrustSettingsDomainAdmin, &trustSettings) == errSecSuccess && trustSettings != NULL) {
|
||||
if (inputTrust == NULL) {
|
||||
inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
|
||||
}
|
||||
if (inputTrust == NULL) {
|
||||
CFRelease(trustSettings);
|
||||
goto errOut;
|
||||
}
|
||||
addTrustSettingsToInputTrust(env, jm_listAdd, trustSettings, inputTrust);
|
||||
CFRelease(trustSettings);
|
||||
}
|
||||
|
||||
// Only add certificates with trust settings
|
||||
if (inputTrust == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// See KeychainStore::createTrustedCertEntry for content of inputTrust
|
||||
jobject inputTrust = (*env)->NewObject(env, jc_arrayListClass, jm_arrayListCons);
|
||||
if (inputTrust == NULL) {
|
||||
CFRelease(trustSettings);
|
||||
goto errOut;
|
||||
}
|
||||
|
||||
// Dump everything inside trustSettings into inputTrust
|
||||
CFIndex count = CFArrayGetCount(trustSettings);
|
||||
for (int i = 0; i < count; i++) {
|
||||
CFDictionaryRef oneTrust = (CFDictionaryRef) CFArrayGetValueAtIndex(trustSettings, i);
|
||||
CFIndex size = CFDictionaryGetCount(oneTrust);
|
||||
const void * keys [size];
|
||||
const void * values [size];
|
||||
CFDictionaryGetKeysAndValues(oneTrust, keys, values);
|
||||
for (int j = 0; j < size; j++) {
|
||||
NSString* s = [NSString stringWithFormat:@"%@", keys[j]];
|
||||
ADD(inputTrust, s);
|
||||
s = [NSString stringWithFormat:@"%@", values[j]];
|
||||
ADD(inputTrust, s);
|
||||
}
|
||||
SecPolicyRef certPolicy;
|
||||
certPolicy = (SecPolicyRef)CFDictionaryGetValue(oneTrust, kSecTrustSettingsPolicy);
|
||||
if (certPolicy != NULL) {
|
||||
CFDictionaryRef policyDict = SecPolicyCopyProperties(certPolicy);
|
||||
ADD(inputTrust, @"SecPolicyOid");
|
||||
NSString* s = [NSString stringWithFormat:@"%@", CFDictionaryGetValue(policyDict, @"SecPolicyOid")];
|
||||
ADD(inputTrust, s);
|
||||
CFRelease(policyDict);
|
||||
}
|
||||
ADDNULL(inputTrust);
|
||||
}
|
||||
CFRelease(trustSettings);
|
||||
|
||||
// Find the creation date.
|
||||
jlong creationDate = getModDateFromItem(env, theItem);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue