I am trying to connect Azure SQL Database using Android Application, While connecting to the Azure SQL database, I am getting SSL Handshake aborted issue. I am using the latest android studio 4.1.2 version and the Android Version was Lollipop 5.0. and also I added a TLS certificate to the application.
Any idea how to fix it ??
Here is my java code :
public static void SetUpHttpsConnection(String urlString) {
String response = null;
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
System.out.println("Loading Certificate from Assets folder ....");
InputStream caInput = new BufferedInputStream(MainActivity.context.getAssets().open("ca-bundle.crt"));
X509Certificate caCertificate = (X509Certificate) cf.generateCertificate(caInput);
Certificate ca = cf.generateCertificate(caInput);
System.out.println("generate certificate .............");
System.out.println("ca : " + (caCertificate).getSubjectDN());
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", caCertificate);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
System.out.println(" Trust Manager Factory ------ ");
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context1 = SSLContext.getInstance("TLS");
//SSLContext context1 = SSLContext.getInstance("TLSv1.2");
System.out.println(" ------------------------------- ");
//context1.init(null, tmf.getTrustManagers(), null);
System.out.println("SSL context ---- :" + context1);
context1.init(null, new X509TrustManager[]{new X509TrustManager(){
@SuppressLint("TrustAllX509TrustManager")
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {}
@SuppressLint("TrustAllX509TrustManager")
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}}}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(
context1.getSocketFactory());
System.out.println("Trust Certificates ----- ");
// Tell the URLConnection to use a SocketFactory from our SSLContext
URL url = new URL(urlString);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
if (urlConnection instanceof HttpsURLConnection) {
HttpsURLConnection httpsConn = (HttpsURLConnection) urlConnection;
httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0,null));
httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());
httpsConn.setRequestProperty("Connection", "Keep-Alive");
httpsConn.setRequestProperty("Charset", "UTF-8");
}
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(2500);
urlConnection.setReadTimeout(3500);
urlConnection.setRequestProperty("Content-Type", "application/json");
int statuscode = urlConnection.getResponseCode();
Log.d("Status code :", Integer.toString(statuscode));
InputStream inputStream = urlConnection.getInputStream();
if (inputStream != null) {
response = streamToString(inputStream);
inputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static String readStream(InputStream is) throws IOException {
final BufferedReader reader = new BufferedReader(new InputStreamReader(is, Charset.forName("US-ASCII")));
StringBuilder total = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
total.append(line);
}
if (reader != null) {
reader.close();
}
return total.toString();
}
private static String streamToString(InputStream inputStream) throws IOException {
StringBuffer sb = new StringBuffer();
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = rd.readLine())!= null) {
sb.append(line);
}
return sb.toString();
}
@SuppressLint("StaticFieldLeak")
private class Azure_Connection extends AsyncTask<String, Void, Iterable<Test>> {
String res = "";
private String rowKey;
@Override
protected void onPreExecute() {
super.onPreExecute();
Toast.makeText(MainActivity.this, "Please wait...", Toast.LENGTH_SHORT)
.show();
}
protected Iterable<Test> doInBackground(String... arg0) {
try {
Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
System.out.println("Reading JDBC Driver");
String UserName = "username@iwavesqlserver";
String Passwrd = "*******";
String ConnectionString = "jdbc:jtds:sqlserver://iwavesqlserver.database.windows.net:1433/iwave_db_1;loginTimeout=300;ssl=require;" +
"integratedSecurity=true;encrypt=false;TrustServerCertificate=true;hostNameInCertificate=*.database.windows.net;";
System.out.println(" .......... Connecting to the SQL Database .......... ");
String urlString = "https://portal.azure.com/#home";
SetUpHttpsConnection(urlString);
try {
Connection connection = DriverManager.getConnection(ConnectionString, UserName, Passwrd);
if (connection != null) {
System.out.println("Database connection success");
}
Statement stmt = Objects.requireNonNull(connection).createStatement();
ResultSet resultSet = stmt.executeQuery("SELECT * FROM test");
log.info("Database Connection test : " + connection);
} catch (SQLException e) {
e.printStackTrace();
}
}catch (Exception e) {
System.out.println(e.getMessage());
}
return null;
}
}
Error message :
I/System.out: Connection Exception : java.sql.SQLException: Network error IOException: SSL handshake aborted: ssl=0xebc432c8: I/O error during system call, Broken pipe
W/System.err: java.sql.SQLException: Network error IOException: SSL handshake aborted: ssl=0xebc432c8: I/O error during system call, Broken pipe
W/System.err: at net.sourceforge.jtds.jdbc.JtdsConnection.<init>(JtdsConnection.java:436)
W/System.err: at net.sourceforge.jtds.jdbc.Driver.connect(Driver.java:184)
at java.sql.DriverManager.getConnection(DriverManager.java:569)
W/System.err: at java.sql.DriverManager.getConnection(DriverManager.java:219)
at com.iwavesys.cloudazure.MainActivity$Azure_Connection.doInBackground(MainActivity.java:381)
at com.iwavesys.cloudazure.MainActivity$Azure_Connection.doInBackground(MainActivity.java:316)
W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:333)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
W/System.err: Caused by: javax.net.ssl.SSLHandshakeException: SSL handshake aborted: ssl=0xebc432c8: I/O error during system call, Broken pipe
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
I am not sure this is the correct way to add certificates and get a connection to the Azure SQL database. please anyone help me to solve this issue.
Thank you.