0

Context: I'm receiving a 400 error when attempting to get a crumb from a Jenkins CI server via Java's HttpsURLConnection class. A Python utility that I wrote makes the call successfully with no problems, as does wget. Here's the Java code:

String crumb_url = JENKINS_URL + "crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"; String userpass = config.getProperty("USERNAME") + ":" + config.getProperty("API_TOKEN"); String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes()); URL url = new URL(crumb_url); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(sslFactory); conn.setRequestMethod("GET"); conn.setRequestProperty("Authorization", basicAuth); conn.setRequestProperty("User-Agent", "XXXXXXXXXX/1.0"); BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); 

The call to create the BufferedReader is where I get an IOException indicating that I got a 400 from the server. Since I'm getting a 400 instead of a certificate-related exception, I'm pretty sure the SSL stuff is working properly. I turned on debug info to see exactly what was being sent, and this is what it's telling me:

HTTPS GET header

Sorry about redacting some of the info, but it shouldn't be relevant. My main concern is the 16 bytes highlighted at the beginning of the request, and that the extra data may be why the Jenkins server is unhappy. Otherwise, the request looks practically identical to what wget sends, with the exception of "Keep-Alive" in wget vs. "keep-alive" in Java. I also attempted to generate the request by hand in case the capitalization difference was the problem, but I still get the 16 byte prefix before the GET. I'm also somewhat curious about the trailing data after the request, but I suspect as long as I have the two CR/LFs at the end it shouldn't matter.

If anyone has any ideas on how to resolve this, I'm all ears. Thanks.

2
  • Try turning on debug info with wget or Python to see what headers they send. Commented Aug 10, 2018 at 16:48
  • Thanks - I already had wget dumping the header/body data for the request. I'd use Wireshark, but don't have access to the key to decode the packets directly. Commented Aug 10, 2018 at 17:02

2 Answers 2

0

I can address your 'main concern' but not your problem :-(

Padded plaintext before ENCRYPTION strongly suggests this was captured inside your TLS stack, since you're using Java probably by javax.net.debug. When TLS sends application data, which for HTTPS is the HTTP request or response, it adds several things depending on the protocol and ciphersuite in use. For an AES (or possibly but much less common Camellia SEED or ARIA) CBC cipher in TLS 1.1 or 1.2, it adds a 16-byte IV at the beginning, and an HMAC and padding at the end. The data at the end of your screenshot after the double-CRLF is valid for a TLS CBC 'GenericBlock' record if the selected HMAC is SHA384, which it might be since you didn't say which ciphersuite was used.

However, that means the request you are actually sending at the app level looks valid, which doesn't help with your 400.

Although, /:, in your query part are in the RFC2396 reserved set and " is excluded which are supposed to be percent-encoded. Webservers and apps vary wildly in how they handle this, and I have no idea if Jenkins cares.

Sign up to request clarification or add additional context in comments.

1 Comment

Spot on regarding the javax.net.debug observation . ;-) Thanks for the info, and the percent-encoding for the path is something I'll look at. It may very well be the problem.
0

The percent-encoding of the URL was the problem. Thanks to all that answered!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.