HTTPS Post request (not) using certificate/hash print? - java

I admit there is a possibility that I am not well informed about the subject, but I've done a LOADS of reading and I still can't get answer to my question.
From what I have learnt, to make communication secure with HTTPS I need to be using some sort of public key (reminds me of pgp-encryption).
My goal is to make a secured POST request from my java application (which I, in the moment it starts working, will rewrite to Android app, if it matters) to a php application accessible via https address.
Naturally I did some Google research on the topic and I got a lot of results how to make ssl connection. Non of those results used any sort of certificate/hash prints. They just use HttpsURLConnection instead of HttpURLConnection, everything else is almost identical.
Right now, almost copy paste of something I found here is this:
String httpsURL = "https://xx.yyyy.zzz/requestHandler.php?getParam1=value1&getParam2=value2";
String query = "email=" + URLEncoder.encode("abc#xyz.com", "UTF-8");
query+="&";
query+="password="+URLEncoder.encode("tramtarie","UTF-8");
URL myurl = new URL(httpsURL);
HttpsURLConnection con = (HttpsURLConnection) myurl.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-length",String.valueOf(query.length()));
con.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
con.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 5.0;Windows98;DigExt)");
con.setDoOutput(true);
con.setDoInput(true);
DataOutputStream output = new DataOutputStream(con.getOutputStream());
output.writeBytes(query);
output.close();
DataInputStream input = new DataInputStream(con.getInputStream());
for(
int c = input.read();
c!=-1;c=input.read())
System.out.print((char)c);
input.close();
System.out.println("Resp Code:"+con.getResponseCode());
System.out.println("Resp Message:"+con.getResponseMessage());
Which sadly does not work and ends up with this exception:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching app.elessy.cz found
This probably means that it checks the certificate and finds out that the certificate I am using does not match domain name for which is registered (it is webhosting certificate, registered for webhosting domain, not the domain I own, the only reason I am using https is to secure data for internal purposes, I do not want this site to be visited by users from outside, so this certificate should be ok).
There are two things that I just don't get about the code and everything.
No code I have been able to find use MD5/SHA-1 (supposedly the public keys for message encryption?) prints or
certificate, they just somehow automatically connect to https
website and should work. Doesn't work for me though.
Do I really need those md5/sha-1 prints that are provided to me? Or at least, what in the given context do those prints mean?
Edit:
Following the given answer and duplicate mark, I managed to get it working - in the meaning that I can communicate with application behind https.
But I didnt have to use any sort of md5/sha1 print. How do I know now that it is safe? Does this protocol on his own? Like that communication is secured either way, when I use built-in java classes to connect to app behind https?
I probably do not seek for precise technical explanation, but more for an assurance that yes - the communication is safe even though I do not use (knowingly) certificate/servers public key to encrypt my messages. That it does the ssl connection for me.

Related

Extra data in HTTPS GET request when using HttpsURLConnection?

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.
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.
The percent-encoding of the URL was the problem. Thanks to all that answered!

java.security.cert.CertificateException: No subject alternative names matching IP address

I have different issues with this exception, Please try to understand.
I'm sending data from one application to another through web service call in Java.
whenever I called it will connect to some other application. in that
a situation I get the above exception, this problem occur only in
byte Grid server.
We solved above problem like this our admin removed security,
means we have https they removed s so we are working with
HTTP, but it's not good, I want to connect through web service call with security, can any one give me the best idea.Please see my sample code
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
String request = PropertyFactory.getProperty("someUrl");
url = new URL(request);
postConnection = (HttpURLConnection) url.openConnection();
can I handle through code?
If you are using Oracle JDK between 1.8.0_51 and 1.8.0_60, there was an issue when connecting via IP address instead of hostname. In the case of using the IP-address, this address also has to be mentioned in the Subject alternative names of the cert. According to Mulesoft Support a workaround would be to set the JVM argument "jdk.tls.trustNameService" to true - resulting in a reverse name lookup for the IP address.
Byte grid having internal firewall so its may be stop, Please contact with byte grid team.

How to send special character via HTTP post request made in Java

I need to send data to another system in a Java aplication via HTTP POST method. Using the Apache HttpClient library is not an option.
I create a URL, httpconection without problems. But when sending special character like Spanish Ñ, the system complains it is receiving
Ñ instead of Ñ.
I've read many post, but I don't understand some things:
When doing a POST connection, and writing to the connection object, is it mandatory to do the URLEncode.encode(data,encoding) to the data being sent?
When sending the data, in some examples I have seen they use the
conn.writeBytes(strData), and in other I have seen conn.write(strData.getBytes(encoding)). Which one is it better? Is it related of using the encode?
Update:
The current code:
URL url = new URL(URLstr);
conn1 = (HttpsURLConnection) url.openConnection();
conn1.setRequestMethod("POST");
conn1.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn1.getOutputStream());
wr.writeBytes(strToSend);//data sent
wr.flush();
wr.close();
(later I get the response)
strToSend has been previously URLENCODE.encode(,"UTF-8")
I still don't know if I must use urlencode in my code and/or setRequestProperty("Contentype","application/x-www-formurlencode");
Or if I must use .write(strToSend.getByte(??)
Any ideas are welcome. I am testing also the real server (I dont know very much about it)

Java: handling webcal protocol

I'm trying to download - or even just open a stream - to a calendar located at webcal://www.somewhere.com/foo?etc=bar.
The Java URL class is throwing a "unknown protocol: webcal" exception when I do:
URL url = new URL("webcal://...");
How can I tell the URL class that it should just use HTTP as trasport protocol even if the web resource is located somewhere behind a webcal:// protocol?
Or, in any case, how can I get my calendar downloaded?
Please, bear in mind that the web server I'm calling does not serve the calendar if I try to replace the "webcal://" with "http://".
As far as I understand, Apple's use of "webcal" really is just a synonym for "http"; so it's supposed to work.
The "webcal://" is an unofficial URI scheme, see Wikipedia article on it.
As such it might stand for one or another back end implementation - e.g. the web server you are calling might be using any of the mentioned protocol implementations, such as WebDAV, CalDAV or OpenDAV
However if all you want is to read the contents of the file, then any HTTP client should do the trick, because the above mentioned protocols are based on HTTP.
Here is an example on how to read a remote iCal using URL's own mechanism for opening HttpURLConnection :
URL calendarURL = new URL("http://www.facebook.com/ical/b.php?uid=myUID&key=myKEY");
URLConnection connection = calendarURL.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while (reader.ready()) {
System.out.println(reader.readLine());
}
As you can see I have changed the original URL from
webcal://www.facebook.com/ical/b.php?uid=MYUID&key=MYKEY
to
http://www.facebook.com/ical/b.php?uid=MYUID&key=MYKEY
, because we use a java.net.URL and by default Java does not recognize this protocol. If indeed the web server you want to contact only serves the content over webcal:// then you might need to use the appropriate client (based on the exact protocol implementation the server uses). For example there are a multitude of frameworks that provide WebDAV client capabilities, such as JackRabbit, Sardine, etc.
If you provide more information on the type of server we can dig further.

Infinite redirect loop in HTTP request

I'm getting a too many redirects redirect error from URLConnection when trying to fetch www.palringo.com
URL url = new URL("http://www.palringo.com/");
HttpURLConnection.setFollowRedirects(true);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
System.out.println("Response code = " + connection.getResponseCode());
outputs the dreaded:
Exception in thread "main" java.net.ProtocolException: Server redirected too many times (20)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
According to wget there is just one redirect, from www.palringo.com to www.palringo.com/en/gb/
Any ideas why my request using URLConnection for /en/gb results in another 302 response for the same resource ?
The problem is exemplified by:
URL url = new URL("http://www.palringo.com/en/gb/");
HttpURLConnection.setFollowRedirects(false);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Just for testing, use Chrome header, to eliminate "anti-crawler" response!
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/11.04 Chromium/12.0.742.112 Chrome/12.0.742.112 Safari/534.30");
System.out.println("Response code = " + connection.getResponseCode());
This outputs:
Response code = 302
Redirected to /en/gb/
hence an infinite redirect loop.
Interestingly although browsers and wget handle it, curl does not:
joel#bohr:/tmp$ curl http://www.palringo.com/en/gb/
curl: (7) couldn't connect to host
A request for /en/gb/ is redirected to /en/gb/ precisely once.
The problem is that your HttpURLConnection (or whatever code you use -- sorry, I'm NOT familiar with Java) does not use cookies.
Disable cookies in browser and observe exactly the same behaviour -- infinite redirect.
The reason: Server checks if cookie is set. If not set -- it sets it and redirects. Because cookies are not supported/disabled, script on server side redirects over and over again.
Solution: Enable/add cookie support to your code and try again.
I think that redirect is defined with pattern like /* -> /en/gb
So, when you arrive to /en/gb the redirect rule works again.
Check your redirect rules. Where are they defined? In apache web server or in other place? Check all. Verify that this is (or is not) a case and fix the rules accordingly.
The problem is on the server side. It might be a broken Apache httpd rewrite rule that is sending redirects that loop back to the same place. It might be something else. Whatever it is, you are unlikely to be able to fix it on the client side.
I'm basically running a crawler and just noticed this issue.
Ah.
It is possible that it is an anti-crawler defence measure. "Hmmm ... looks like one of those pesky crawlers who ignore my robots.txt file, waste all of my bandwidth and steal my precious content. Lets cause him some pain with a redirect loop!!".
Check that your crawler is obeying the "robots.txt" protocol. Check the ToS for the site you are crawling to see if what you are doing is allowed.
You could be right, but if so how come wget and browsers handle this with just the one redirect?
Maybe because the server is looking at the request headers, or at your pattern of requests.
The Terms of Service (that I see) say this:
"You agree to not use the Service to: ... xiii - Run any automated systems, processes, scripts or bots for any purpose without the express written permission of Palringo."
Arguably, crawling their site is in violation of that.
You will also get this error if you're trying to connect to a service that requires authentication and you provide wrong username and password.

Categories

Resources