-
Notifications
You must be signed in to change notification settings - Fork 1.2k
pkix/est: NullPointerException on HTTP/1.1 Transfer-Encoding chunked during ESTResponse processing #1324
Description
Problem Statement
I am using EST simpleEnroll (bcpkix-jdk18on, 1.72) against an EST Server which answers the request using Transfer-Encoding Chunked. When the response is processed, the following exception occurs:
Exception in thread "main" org.bouncycastle.est.ESTException: Cannot invoke "java.lang.Long.longValue()" because "this.max" is null HTTP Status Code: 0
at org.bouncycastle.est.ESTService.enroll(ESTService.java:322)
at org.bouncycastle.est.ESTService.simpleEnroll(ESTService.java:352)
at com.bbraun.cit.pki.est.Main.main(Main.java:59)
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Long.longValue()" because "this.max" is null
at org.bouncycastle.est.CTEBase64InputStream.pullFromSrc(CTEBase64InputStream.java:43)
at org.bouncycastle.est.CTEBase64InputStream.read(CTEBase64InputStream.java:104)
at java.base/java.io.FilterInputStream.read(FilterInputStream.java:82)
at org.bouncycastle.asn1.ASN1InputStream.readObject(ASN1InputStream.java:189)
at org.bouncycastle.est.ESTService.handleEnrollResponse(ESTService.java:634)
at org.bouncycastle.est.ESTService.enroll(ESTService.java:311)
... 2 more
Problem Analysis
The problematic code starts in ESTResponse:
bc-java/pkix/src/main/java/org/bouncycastle/est/ESTResponse.java
Lines 165 to 168 in c8ff5b1
| if ("base64".equalsIgnoreCase(getHeader("content-transfer-encoding"))) | |
| { | |
| inputStream = new CTEBase64InputStream(inputStream, getContentLength()); | |
| } |
When we have a chunked transfer, getContentLength() returns null since no content length is known before the transfer is complete. So CTEBase64InputStream's constructor receives null as its reading limit max. This leads to the fact that, CTEBase64InputStream#pullFromSrc produces the above mentioned NPE on the following line:
| if (this.read >= this.max) | |
| { | |
| return -1; | |
| } |
Solution
Passing a reading limit is not feasible when dealing with chunked transfers since the Content-Length header is not set. Besides chunked transfers, passing a reading limit is not neccessray at all since all inputStreams which are passed to the constructor return -1 when finished. All CTEBase64InputStream's methods respect this convention and consider the processing to be finished. Hence, removing this reading limit is fine.
I created a patch and tested it against real world servers. Chunked Transfers and non chunked transfers are working.
I am happy to provide a PR.