Skip to content

pkix/est: NullPointerException on HTTP/1.1 Transfer-Encoding chunked during ESTResponse processing #1324

@adippel

Description

@adippel

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:

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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions