Skip to content

Commit dbbad6f

Browse files
committed
ZOOKEEPER-4992: Avoid overriding same-subject certs in PEM trust store
Signed-off-by: Tero Saarni <tero.saarni@est.tech>
1 parent e8e141b commit dbbad6f

File tree

4 files changed

+28
-16
lines changed

4 files changed

+28
-16
lines changed

zookeeper-server/src/main/java/org/apache/zookeeper/util/PemReader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ public static KeyStore loadTrustStore(File certificateChainFile) throws IOExcept
9292
keyStore.load(null, null);
9393

9494
List<X509Certificate> certificateChain = readCertificateChain(certificateChainFile);
95+
int i = 1;
9596
for (X509Certificate certificate : certificateChain) {
9697
X500Principal principal = certificate.getSubjectX500Principal();
97-
keyStore.setCertificateEntry(principal.getName("RFC2253"), certificate);
98+
keyStore.setCertificateEntry(principal.getName("RFC2253") + "-" + i++, certificate);
9899
}
99100
return keyStore;
100101
}

zookeeper-server/src/test/java/org/apache/zookeeper/common/PEMFileLoaderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public void testLoadKeyStoreWithWrongFileType(
108108

109109
@ParameterizedTest
110110
@MethodSource("data")
111-
public void testLoadTrustStore(
111+
public void testLoadTrustStoreFromPemBundle(
112112
X509KeyType caKeyType, X509KeyType certKeyType, String keyPassword, Integer paramIndex)
113113
throws Exception {
114114
init(caKeyType, certKeyType, keyPassword, paramIndex);
@@ -118,7 +118,7 @@ public void testLoadTrustStore(
118118
.setTrustStorePassword(x509TestContext.getTrustStorePassword())
119119
.build()
120120
.loadTrustStore();
121-
assertEquals(1, ts.size());
121+
assertEquals(2, ts.size());
122122
}
123123

124124
@ParameterizedTest

zookeeper-server/src/test/java/org/apache/zookeeper/common/X509TestContext.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import java.security.Security;
3030
import java.security.cert.X509Certificate;
3131
import java.util.Arrays;
32+
import java.util.List;
33+
3234
import org.apache.commons.io.FileUtils;
3335
import org.bouncycastle.asn1.x500.X500NameBuilder;
3436
import org.bouncycastle.asn1.x500.style.BCStyle;
@@ -48,7 +50,7 @@ public class X509TestContext {
4850
private final X509KeyType trustStoreKeyType;
4951
private final KeyPair trustStoreKeyPair;
5052
private final long trustStoreCertExpirationMillis;
51-
private final X509Certificate trustStoreCertificate;
53+
private final List<X509Certificate> trustStoreCertificates;
5254
private final String trustStorePassword;
5355
private File trustStoreJksFile;
5456
private File trustStorePemFile;
@@ -99,11 +101,18 @@ private X509TestContext(File tempDir, KeyPair trustStoreKeyPair, long trustStore
99101

100102
X500NameBuilder caNameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
101103
caNameBuilder.addRDN(BCStyle.CN, MethodHandles.lookup().lookupClass().getCanonicalName() + " Root CA");
102-
trustStoreCertificate = X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair, trustStoreCertExpirationMillis);
104+
// Create two CA certs to test multiple certs in PEM bundles.
105+
// Use same subject name to simulate multiple CA certs from the same CA.
106+
trustStoreCertificates = Arrays.asList(
107+
X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair,
108+
trustStoreCertExpirationMillis),
109+
X509TestHelpers.newSelfSignedCACert(caNameBuilder.build(), trustStoreKeyPair,
110+
trustStoreCertExpirationMillis)
111+
);
103112

104113
X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE);
105114
nameBuilder.addRDN(BCStyle.CN, MethodHandles.lookup().lookupClass().getCanonicalName() + " Zookeeper Test");
106-
keyStoreCertificate = X509TestHelpers.newCert(trustStoreCertificate, trustStoreKeyPair, nameBuilder.build(), keyStoreKeyPair.getPublic(), keyStoreCertExpirationMillis);
115+
keyStoreCertificate = X509TestHelpers.newCert(trustStoreCertificates.get(0), trustStoreKeyPair, nameBuilder.build(), keyStoreKeyPair.getPublic(), keyStoreCertExpirationMillis);
107116
trustStorePkcs12File = trustStorePemFile = trustStoreJksFile = null;
108117
keyStorePkcs12File = keyStorePemFile = keyStoreJksFile = null;
109118

@@ -139,8 +148,8 @@ public long getTrustStoreCertExpirationMillis() {
139148
return trustStoreCertExpirationMillis;
140149
}
141150

142-
public X509Certificate getTrustStoreCertificate() {
143-
return trustStoreCertificate;
151+
public X509Certificate getTrustStoreCertificates() {
152+
return trustStoreCertificates.get(0);
144153
}
145154

146155
public String getTrustStorePassword() {
@@ -159,7 +168,7 @@ public File getTrustStoreFile(KeyStoreFileType storeFileType) throws IOException
159168
case JKS:
160169
return getTrustStoreJksFile();
161170
case PEM:
162-
return getTrustStorePemFile();
171+
return getTrustStorePemBundleFile();
163172
case PKCS12:
164173
return getTrustStorePkcs12File();
165174
case BCFKS:
@@ -177,7 +186,7 @@ private File getTrustStoreJksFile() throws IOException {
177186
File trustStoreJksFile = File.createTempFile(TRUST_STORE_PREFIX, KeyStoreFileType.JKS.getDefaultFileExtension(), tempDir);
178187
trustStoreJksFile.deleteOnExit();
179188
try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStoreJksFile)) {
180-
byte[] bytes = X509TestHelpers.certToJavaTrustStoreBytes(trustStoreCertificate, trustStorePassword);
189+
byte[] bytes = X509TestHelpers.certToJavaTrustStoreBytes(trustStoreCertificates.get(0), trustStorePassword);
181190
trustStoreOutputStream.write(bytes);
182191
trustStoreOutputStream.flush();
183192
} catch (GeneralSecurityException e) {
@@ -188,11 +197,13 @@ private File getTrustStoreJksFile() throws IOException {
188197
return trustStoreJksFile;
189198
}
190199

191-
private File getTrustStorePemFile() throws IOException {
200+
private File getTrustStorePemBundleFile() throws IOException {
192201
if (trustStorePemFile == null) {
193202
File trustStorePemFile = File.createTempFile(TRUST_STORE_PREFIX, KeyStoreFileType.PEM.getDefaultFileExtension(), tempDir);
194203
trustStorePemFile.deleteOnExit();
195-
FileUtils.writeStringToFile(trustStorePemFile, X509TestHelpers.pemEncodeX509Certificate(trustStoreCertificate), StandardCharsets.US_ASCII, false);
204+
for (X509Certificate cert : trustStoreCertificates) {
205+
FileUtils.writeStringToFile(trustStorePemFile, X509TestHelpers.pemEncodeX509Certificate(cert), StandardCharsets.US_ASCII, true);
206+
}
196207
this.trustStorePemFile = trustStorePemFile;
197208
}
198209
return trustStorePemFile;
@@ -203,7 +214,7 @@ private File getTrustStorePkcs12File() throws IOException {
203214
File trustStorePkcs12File = File.createTempFile(TRUST_STORE_PREFIX, KeyStoreFileType.PKCS12.getDefaultFileExtension(), tempDir);
204215
trustStorePkcs12File.deleteOnExit();
205216
try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStorePkcs12File)) {
206-
byte[] bytes = X509TestHelpers.certToPKCS12TrustStoreBytes(trustStoreCertificate, trustStorePassword);
217+
byte[] bytes = X509TestHelpers.certToPKCS12TrustStoreBytes(trustStoreCertificates.get(0), trustStorePassword);
207218
trustStoreOutputStream.write(bytes);
208219
trustStoreOutputStream.flush();
209220
} catch (GeneralSecurityException e) {
@@ -220,7 +231,7 @@ private File getTrustStoreBcfksFile() throws IOException {
220231
TRUST_STORE_PREFIX, KeyStoreFileType.BCFKS.getDefaultFileExtension(), tempDir);
221232
trustStoreBcfksFile.deleteOnExit();
222233
try (final FileOutputStream trustStoreOutputStream = new FileOutputStream(trustStoreBcfksFile)) {
223-
byte[] bytes = X509TestHelpers.certToBCFKSTrustStoreBytes(trustStoreCertificate, trustStorePassword);
234+
byte[] bytes = X509TestHelpers.certToBCFKSTrustStoreBytes(trustStoreCertificates.get(0), trustStorePassword);
224235
trustStoreOutputStream.write(bytes);
225236
trustStoreOutputStream.flush();
226237
} catch (GeneralSecurityException e) {

zookeeper-server/src/test/java/org/apache/zookeeper/util/PemReaderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ public void testLoadCertificateFromTrustStore(
135135
throws Exception {
136136
init(caKeyType, certKeyType, keyPassword, paramIndex);
137137
List<X509Certificate> certs = PemReader.readCertificateChain(x509TestContext.getTrustStoreFile(KeyStoreFileType.PEM));
138-
assertEquals(1, certs.size());
139-
assertEquals(x509TestContext.getTrustStoreCertificate(), certs.get(0));
138+
assertEquals(2, certs.size());
139+
assertEquals(x509TestContext.getTrustStoreCertificates(), certs.get(0));
140140
}
141141

142142
}

0 commit comments

Comments
 (0)