瀏覽代碼

Fix for PemTrustConfigTests.testTrustConfigReloadsFileContents failure (#43539)

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
Yogesh Gaikwad 6 年之前
父節點
當前提交
7054a42030
共有 1 個文件被更改,包括 24 次插入3 次删除
  1. 24 3
      libs/ssl-config/src/test/java/org/elasticsearch/common/ssl/PemTrustConfigTests.java

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

@@ -22,7 +22,6 @@ package org.elasticsearch.common.ssl;
 import org.elasticsearch.test.ESTestCase;
 import org.hamcrest.Matchers;
 
-import javax.net.ssl.X509ExtendedTrustManager;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
@@ -37,6 +36,8 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import javax.net.ssl.X509ExtendedTrustManager;
+
 public class PemTrustConfigTests extends ESTestCase {
 
     public void testBuildTrustConfigFromSinglePemFile() throws Exception {
@@ -57,7 +58,7 @@ public class PemTrustConfigTests extends ESTestCase {
 
     public void testBadFileFormatFails() throws Exception {
         final Path ca = createTempFile("ca", ".crt");
-        Files.write(ca, randomByteArrayOfLength(128), StandardOpenOption.APPEND);
+        Files.write(ca, generateRandomByteArrayOfLength(128), StandardOpenOption.APPEND);
         final PemTrustConfig trustConfig = new PemTrustConfig(Collections.singletonList(ca));
         assertThat(trustConfig.getDependentFiles(), Matchers.containsInAnyOrder(ca));
         assertInvalidFileFormat(trustConfig, ca);
@@ -106,7 +107,7 @@ public class PemTrustConfigTests extends ESTestCase {
         Files.delete(ca1);
         assertFileNotFound(trustConfig, ca1);
 
-        Files.write(ca1, randomByteArrayOfLength(128), StandardOpenOption.CREATE);
+        Files.write(ca1, generateRandomByteArrayOfLength(128), StandardOpenOption.CREATE);
         assertInvalidFileFormat(trustConfig, ca1);
     }
 
@@ -148,4 +149,24 @@ public class PemTrustConfigTests extends ESTestCase {
         assertThat(exception.getMessage(), Matchers.containsString(file.toAbsolutePath().toString()));
         assertThat(exception.getCause(), Matchers.instanceOf(NoSuchFileException.class));
     }
+
+    private byte[] generateRandomByteArrayOfLength(int length) {
+        byte[] bytes = randomByteArrayOfLength(length);
+        /*
+         * If the bytes represent DER encoded value indicating ASN.1 SEQUENCE followed by length byte if it is zero then while trying to
+         * parse PKCS7 block from the encoded stream, it failed parsing the content type. The DerInputStream.getSequence() method in this
+         * case returns an empty DerValue array but ContentType does not check the length of array before accessing the array resulting in a
+         * ArrayIndexOutOfBoundsException. This check ensures that when we create random stream of bytes we do not create ASN.1 SEQUENCE
+         * followed by zero length which fails the test intermittently.
+         */
+        while(checkRandomGeneratedBytesRepresentZeroLengthDerSequenceCausingArrayIndexOutOfBound(bytes)) {
+            bytes = randomByteArrayOfLength(length);
+        }
+        return bytes;
+    }
+
+    private static boolean checkRandomGeneratedBytesRepresentZeroLengthDerSequenceCausingArrayIndexOutOfBound(byte[] bytes) {
+        // Tag value indicating an ASN.1 "SEQUENCE". Reference: sun.security.util.DerValue.tag_Sequence = 0x30
+        return bytes[0] == 0x30 && bytes[1] == 0x00;
+    }
 }