I have a self signed server hardcoded port 52428. My client app keeps getting "Hostname Was Not Verified" even when I override the HostNameVerifier to always return true. When I changed the hostname from IP Address to DNS, another error pops up that says "Unable to resolve host: No Address associated with hostname"
Here's my code:
private class SSLConnect extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... values) {
//String https_url = "https://www.google.com/";
//String https_url = "https://192.168.0.106:52428/webserveradmin/preferences";
String https_url = "https://home-pc:52428/webserveradmin/preferences/";
String response;
try {
TrustManager[] tm = new TrustManager[]{
new X509TrustManager() {
#Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
//return new X509Certificate[0];
return null;
}
}
};
URL url;
try {
url = new URL(https_url);
}
catch (MalformedURLException e) {
return "Error URL: " + e.getMessage();
}
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
try {
conn.setDefaultHostnameVerifier(new NullHostNameVerifier());
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, tm, new SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Basic " + Base64.encode("sa:sa".getBytes(), Base64.DEFAULT));
conn.connect();
InputStream in = conn.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder sb = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
sb.append(line);
}
response = sb.toString();
} catch (GeneralSecurityException e) {
return "Error Security: " + e.getMessage();
}
}
catch(Exception e){
return "Error SSL: " + e.getMessage();
}
return response;
}
#Override
protected void onProgressUpdate(Void... values) {
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(ctxt, result, Toast.LENGTH_LONG).show();
}
}
public class NullHostNameVerifier implements HostnameVerifier{
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
The hostname verifier cares about verifying the hostname only, not the trust chain. But with self-signed certificates you don't have a trust chain leading to a locally trusted certificate.
Apart from that, just disabling the certificate checking is a very bad idea, because this way you will not only accept your self-signed certificate but instead any certificates and thus you will be open to man-in-the-middle attacks. See also SSL Vulnerability in ******** VU#582497.
To do it correctly use instead certificate/public key pinning. For a more detailed explanation and also sample code see OWSAP.
Related
I'm trying to connect VSTS through REST in JAVA but always getting connect time out. Using this code I'm able to connect with http but always getting error when trying to connect with https. Will be posting the error in comments. Getting this error -> com.sun.jersey.api.client.ClientHandlerException: java.net.SocketTimeoutException: connect timed out
public class RESTInvoker {
public static class ConnectionFactory implements HttpURLConnectionFactory
{
SSLContext sslContext;
public ConnectionFactory() {
}
#Override
public HttpURLConnection getHttpURLConnection(URL url) throws
IOException {
initializeProxy();
HttpURLConnection con = (HttpURLConnection) url.openConnection();
if (con instanceof HttpsURLConnection) {
System.out.println("The valus is....");
HttpsURLConnection httpsCon = (HttpsURLConnection)
url.openConnection();
httpsCon.setHostnameVerifier(getHostnameVerifier());
httpsCon.setSSLSocketFactory(getSslContext().getSocketFactory());
return httpsCon;
} else {
return con;
}
}
public SSLContext getSslContext() {
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[] { new
SecureTrustManager() }, new SecureRandom());
} catch (NoSuchAlgorithmException ex) {
//
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.SEVERE, null,
ex);
} catch (KeyManagementException ex) {
//
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.SEVERE, null,
ex);
}
return sslContext;
}
private HostnameVerifier getHostnameVerifier() {
return new HostnameVerifier() {
#Override
public boolean verify(String hostname, javax.net.ssl.SSLSession
sslSession) {
return true;
}
};
}
public static void main(String[] args) {
String username = "xxx";
String token = "xxx";
String tfsurl = "xxx";
String collectionName = "xxx";
String prjName = "xxxx";
byte[] encodedBytes = Base64.getEncoder().encode(token.getBytes());
System.out.println(encodedBytes);
String ab = "https://" + username + ":" + encodedBytes + "#" +
tfsurl
+ "/Inforce%20Portal/_apis/wit/wiql?api-version=4.0";
// Client client =Client.create();
System.out.println(ab);
try {
String input = "{\"query\":\"Select [System.Id], [System.Title],
[System.State] From WorkItems\"}";
URLConnectionClientHandler cc = new
URLConnectionClientHandler(new ConnectionFactory());
Client client = new Client(cc);
WebResource webResource = client.resource("https://" + username + ":" + token + "#" + tfsurl + "/"
+ prjName + "/_apis/wit/wiql?api-version=4.0");
ClientResponse response = null;
response=webResource.type("application/json").accept("application/json").post(ClientResp
onse.class,
input);
String data = "";
try {
data = response.getEntity(String.class);
System.out.println(data);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
class SecureTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public boolean isClientTrusted(X509Certificate[] arg0) {
return true;
}
public boolean isServerTrusted(X509Certificate[] arg0) {
return true;
}
}
}
}
According to your description, it seems that it is not related to your code.
I recommend that you could check the TFS server whether there is a Https binding.
If there is no Https bindings, please have a try to add the corrosponding Https binds
When trying to access web service from secured testing environment with SSL certificate getting the issue below.
com.android.volley.NoConnectionError: javax.net.ssl.SSLProtocolException: Read error: ssl=0xa35dad40: Failure in SSL library, usually a protocol error
error:100000d7:SSL routines:OPENSSL_internal:SSL_HANDSHAKE_FAILURE (external/boringssl/src/ssl/s3_pkt.c:402 0xa3630912:0x00000000)
I have tried with volley and basic java code, still getting the same issue. When I used the same code for secured development environment with different certificate its working fine. Whereas its not working in testing environment for specific bandwidths (Airtel 3G, 4G). It is working fine with all the environments(Testing & Dev) for 2G bandwidths.
Don't know where the problem occurs. Help me in sorting out this issue.
I have added the code snippet below,
Responsecallback responsecallback;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
testing(mBase_Url);
}
public void testing(String urls) {
String result = "";
try {
URL url = new URL(urls);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(getSSLCertificate()); // Tell the URLConnection to use a SocketFactory from our SSLContext
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setConnectTimeout(30000);
connection.setReadTimeout(30000);
connection.setHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
Uri.Builder builder = new Uri.Builder()
.appendQueryParameter("country", "IN");
String query = builder.build().getEncodedQuery();
PrintWriter out = new PrintWriter(connection.getOutputStream());
out.println(query);
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream())); //,8192
String inputLine;
while ((inputLine = in.readLine()) != null) {
result = result.concat(inputLine);
}
responsecallback.displayResponse(result);
in.close();
} catch (IOException e) {
result = e.toString();
Log.e(TAG, "HTTP Error Result=" + result);
responsecallback.displayResponse(result);
}
}
private SSLSocketFactory getSSLCertificate() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("PKCS12");
// your trusted certificates (root and any intermediate certs)
InputStream in = getResources().openRawResource(R.raw.xxxxxx); //SSL Certificate - P12 formate
String password = "XXXXXXX"; // Certificate password
char[] pwd = password.toCharArray();
try {
trusted.load(in, pwd);
} finally {
in.close();
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(trusted, pwd);
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(trusted);
SSLContext context = SSLContext.getInstance("SSL");
context.init(kmf.getKeyManagers(), getWrappedTrustManagers(), new SecureRandom());
return context.getSocketFactory();
} catch (Exception e) {
Log.e(TAG, "Exception e=" + e.toString());
throw new AssertionError(e);
}
}
private TrustManager[] getWrappedTrustManagers() {
return new TrustManager[]{
new X509TrustManager() {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
X509Certificate[] myTrustedAnchors = new X509Certificate[0];
return null;
}
}
};
}
I'm trying to access a web service through REST API post method and end up with FileNotFoundException
code:
public class TestService {
static {
disableSSLVerification();
}
public static void main(String[] args) {
String[] names = {"login","seq","password"};
String[] values = { "admin", "2811", "admin" };
String url = "https://localhost:8844/login";
try {
httpPost(url, names, values);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String httpPost(String urlStr, String[] paramName, String[] paramVal) throws Exception {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setAllowUserInteraction(false);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream out = conn.getOutputStream();
Writer writer = new OutputStreamWriter(out, "UTF-8");
for (int i = 0; i < paramName.length; i++) {
writer.write(paramName[i]);
writer.write("=");
writer.write(URLEncoder.encode(paramVal[i], "UTF-8"));
writer.write("&");
}
System.out.println("WRITER: " + writer);
writer.close();
out.close();
if (conn.getResponseCode() != 200) {
throw new IOException(conn.getResponseMessage());
}
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
return sb.toString();
}
public static void disableSSLVerification() {
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
SSLContext sc = null;
try {
sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}
Log:
java.io.FileNotFoundException: https://localhost:8844/login
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown S
ource)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So
urce)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unkn
own Source)
can anyone please help me to resolve this? please try to help me rather marking this one 'duplicate'.
It's actually an HttpsURLConnection (you are opening a https:// url).
That URL does not exist, try opening it in your browser. If the url exists it could be that you are using a self-signed certificate on that https host, that is rejected by java urlconnection classes(but i don't think that's the case, the exception should be different, in that case you'll need to implement a wrapper that accept the certificate anyway).
You may try removing:
conn.setDoOutput(true);
conn.setDoInput(true);
since response was not received because there's the problem with the method signature. it has been updated. I have changed accordingly and now it is working fine.
String[] names = {"username","password"};
String[] values = { "admin", "admin" };
String url = "https://localhost:8844/session";
I am trying to get an image from a URL which starts with HTTPS. I keep getting the Hostname was not verified exception.
I took a look at this question java.io.IOException: Hostname was not verified but didn't understood how to make it work.
Is there any way I can allow all hostnames?
Here's the code thats giving me trouble:
public Drawable drawableFromUrl(String url) {
Bitmap x;
HttpURLConnection connection;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.connect();
InputStream input = connection.getInputStream();
x = BitmapFactory.decodeStream(input);
return new BitmapDrawable(x);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
return null;
}
return null;
}
Thanks in advance for your help
This error occurs when the TLS certificate is either self-signed or the domain on the certificate doesn't match the server's host name.
This answer provides a complete solution:
/**
* Disables the SSL certificate checking for new instances of {#link HttpsURLConnection} This has been created to
* aid testing on a local box, not for use on production.
*/
private static void disableSSLCertificateChecking() {
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
// not implemented
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
// not implemented
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
Simply run that once at any time before making your first HTTPS connection. If you control the server, though, it is strongly preferred to try and obtain a valid certificate instead.
I am trying to read the content of the URL with the code down below, but get an 403 error:
https://api.kraken.com/0/public/Time
The URL is reachable in the Problem or via Rest-Connection-Test-Pages like https://apigee.com without a problem. The code works for other HTTPS-Urls just fine. I have no clue what could be wrong here:
public class HttpsClient{
public static void main(String[] args)
{
new HttpsClient().testIt();
}
private void testIt(){
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {
;
}
String https_url = "https://api.kraken.com/0/public/Time";
URL url;
HttpsURLConnection con = null;
try {
url = new URL(https_url);
con = (HttpsURLConnection)url.openConnection();
//dumpl all cert info
print_https_cert(con);
try{
System.out.println("****** Content of the URL ********");
BufferedReader br =
new BufferedReader(
new InputStreamReader(con.getInputStream()));
String input;
while ((input = br.readLine()) != null){
System.out.println(input);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager(){
#Override
public X509Certificate[] getAcceptedIssuers(){return null;}
#Override
public void checkClientTrusted(X509Certificate[] certs, String authType){}
#Override
public void checkServerTrusted(X509Certificate[] certs, String authType){}
}};
}