> The sun.security.ssl.TrustStoreManager.TrustAnchorManager keeps one cached
> TrustStoreDescriptor (path, type, provider, password, last-modified time). It
> uses that descriptor to validate two caches: the loaded KeyStore (ksRef) and
> the extracted trusted certificates (csRef).
>
> getTrustedCerts() replaces the descriptor, ksRef and csRef together when the
> descriptor has changed. getKeyStore() replaces the descriptor and ksRef but
> leaves csRef alone.
>
> If getTrustedKeyStore() runs after the trust store file was modified, the
> cached descriptor is updated while csRef still holds the old certificates. A
> following getTrustedCerts() call finds a matching descriptor and returns the
> old set.
>
> TrustManagerFactory.init((KeyStore) null) then builds a trust manager that
> does not include the new certificates, until the JVM restarts or the weakly
> referenced csRef is cleared by the garbage collector.
>
> The only caller of getTrustedKeyStore() in the JDK is
> SSLContextImpl.DefaultManagersHolder.getTrustManagers(). It runs when the
> default TrustManagerFactory provider is not SunJSSE, so the problem is
> reachable with public APIs only.
>
> Steps to Reproduce:
>
> Create a PKCS12 trust store with one certificate and point
> javax.net.ssl.trustStore, trustStorePassword and trustStoreType at it.
> Build a default trust manager with TrustManagerFactory.getInstance("PKIX",
> "SunJSSE") and init((KeyStore) null), and keep a reference to it. It has 1
> accepted issuer.
> Add a second certificate to the file, making sure its last-modified time
> changes.
> Register a TrustManagerFactory provider that is not SunJSSE at position 1
> (for example, one that delegates to SunJSSE), and call
> SSLContext.getDefault().
> Build another default SunJSSE trust manager as in step 2.
>
> Results
> Expected: The new trust manager has 2 accepted issuers.
> Actual: It has 1.
>
> The new test StaleTrustedCerts implements these steps. It fails on an
> unpatched 21.0.11 and passes with the fix.
>
> Fix
> Clear the cached certificates in getKeyStore() together with the other caches:
>
> this.descriptor = descriptor;
> this.ksRef = new WeakReference<>(ks);
> this.csRef = new WeakReference<>(null);
>
> csRef is private and read only by getTrustedCerts(), which already reloads
> when get() returns null.
>
> Testing
> Included test
> test/jdk/sun/security/ssl/X509TrustManagerImpl/StaleTrustedCerts.java that
> reproduces the issue, and verifies the fix.
>
>
> ---------
> - [x] I confirm that I make this contribution in accordance with the [OpenJDK
> Interim AI Policy](https://openjdk.org/...
Thejasvi Voniadka has updated the pull request incrementally with one
additional commit since the last revision:
Updated copyrights, added comments, and moved the test to the right directory
-------------
Changes:
- all: https://git.openjdk.org/jdk/pull/33545/files
- new: https://git.openjdk.org/jdk/pull/33545/files/9f023334..9798d9b3
Webrevs:
- full: https://webrevs.openjdk.org/?repo=jdk&pr=33545&range=01
- incr: https://webrevs.openjdk.org/?repo=jdk&pr=33545&range=00-01
Stats: 253 lines in 3 files changed: 133 ins; 119 del; 1 mod
Patch: https://git.openjdk.org/jdk/pull/33545.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/33545/head:pull/33545
PR: https://git.openjdk.org/jdk/pull/33545