Skip to content

Commit ca43cdf

Browse files
authored
Fix for PemTrustConfigTests.testTrustConfigReloadsFileContents failure (#43539) (#43613)
The test `PemTrustConfigTests.testTrustConfigReloadsFileContents` failed intermittently with `ArrayIndexOutOfBoundsException` while parsing the randomly generated bytes array representing DER encoded stream. This seems to be a bug in JDK (once confirmed we can raise the bug in JDK bugs system). The problem arises when the `X509Factory#parseX509orPKCS7()` tries to [create `PKCS7` block](https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c59dfd791f62d41f332db9e306bc1422/src/java.base/share/classes/sun/security/provider/X509Factory.java#L460) from der encoded stream. While constructing PKCS7 block it tries to create `ContentInfo` type but fails to do so for the stream where the length after the DER SEQUENCE is 0. `DerInputStream#getSequence` [may return empty array of `DerValue`](https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c59dfd791f62d41f332db9e306bc1422/src/java.base/share/classes/sun/security/util/DerInputStream.java#L409..L412) but [the code in `ContentInfo`](https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c59dfd791f62d41f332db9e306bc1422/src/java.base/share/classes/sun/security/pkcs/ContentInfo.java#L135) does not check for the empty thereby throwing `ArrayIndexOutOfBoundsException`. Closes #42509
1 parent 05e1f55 commit ca43cdf

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

libs/ssl-config/src/test/java/org/elasticsearch/common/ssl/PemTrustConfigTests.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import org.elasticsearch.test.ESTestCase;
2323
import org.hamcrest.Matchers;
2424

25-
import javax.net.ssl.X509ExtendedTrustManager;
2625
import java.nio.file.Files;
2726
import java.nio.file.NoSuchFileException;
2827
import java.nio.file.Path;
@@ -37,6 +36,8 @@
3736
import java.util.stream.Collectors;
3837
import java.util.stream.Stream;
3938

39+
import javax.net.ssl.X509ExtendedTrustManager;
40+
4041
public class PemTrustConfigTests extends ESTestCase {
4142

4243
public void testBuildTrustConfigFromSinglePemFile() throws Exception {
@@ -57,7 +58,7 @@ public void testBuildTrustConfigFromMultiplePemFiles() throws Exception {
5758

5859
public void testBadFileFormatFails() throws Exception {
5960
final Path ca = createTempFile("ca", ".crt");
60-
Files.write(ca, randomByteArrayOfLength(128), StandardOpenOption.APPEND);
61+
Files.write(ca, generateRandomByteArrayOfLength(128), StandardOpenOption.APPEND);
6162
final PemTrustConfig trustConfig = new PemTrustConfig(Collections.singletonList(ca));
6263
assertThat(trustConfig.getDependentFiles(), Matchers.containsInAnyOrder(ca));
6364
assertInvalidFileFormat(trustConfig, ca);
@@ -107,7 +108,7 @@ public void testTrustConfigReloadsFileContents() throws Exception {
107108
Files.delete(ca1);
108109
assertFileNotFound(trustConfig, ca1);
109110

110-
Files.write(ca1, randomByteArrayOfLength(128), StandardOpenOption.CREATE);
111+
Files.write(ca1, generateRandomByteArrayOfLength(128), StandardOpenOption.CREATE);
111112
assertInvalidFileFormat(trustConfig, ca1);
112113
}
113114

@@ -149,4 +150,24 @@ private void assertFileNotFound(PemTrustConfig trustConfig, Path file) {
149150
assertThat(exception.getMessage(), Matchers.containsString(file.toAbsolutePath().toString()));
150151
assertThat(exception.getCause(), Matchers.instanceOf(NoSuchFileException.class));
151152
}
153+
154+
private byte[] generateRandomByteArrayOfLength(int length) {
155+
byte[] bytes = randomByteArrayOfLength(length);
156+
/*
157+
* If the bytes represent DER encoded value indicating ASN.1 SEQUENCE followed by length byte if it is zero then while trying to
158+
* parse PKCS7 block from the encoded stream, it failed parsing the content type. The DerInputStream.getSequence() method in this
159+
* case returns an empty DerValue array but ContentType does not check the length of array before accessing the array resulting in a
160+
* ArrayIndexOutOfBoundsException. This check ensures that when we create random stream of bytes we do not create ASN.1 SEQUENCE
161+
* followed by zero length which fails the test intermittently.
162+
*/
163+
while(checkRandomGeneratedBytesRepresentZeroLengthDerSequenceCausingArrayIndexOutOfBound(bytes)) {
164+
bytes = randomByteArrayOfLength(length);
165+
}
166+
return bytes;
167+
}
168+
169+
private static boolean checkRandomGeneratedBytesRepresentZeroLengthDerSequenceCausingArrayIndexOutOfBound(byte[] bytes) {
170+
// Tag value indicating an ASN.1 "SEQUENCE". Reference: sun.security.util.DerValue.tag_Sequence = 0x30
171+
return bytes[0] == 0x30 && bytes[1] == 0x00;
172+
}
152173
}

0 commit comments

Comments
 (0)