I have two separated servers running Oracle 11g.
The servers were patched with Oracle patch sets to upgrade JVM. After the upgrade, I'm able to communicate with external web service using HTTPS and TLSv1.2, but only on server "A". Server "B" gives me error like:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:142)
at FursTestBaza.Test(FursTestBaza:92)
We have checked patch set and both servers "have" the same patch set installed:
The Java stored procedure is a simple Class
with one static method. This procedure loads certificates from file system and makes a HTTPS connection to specified URL (hardcoded for test purposes). In the source code I have included System.setProperty("javax.net.debug", "all")
to get back some log whats happening.
The source code of Java stored procedure:
CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED INIS_PROD."FursTestBaza" as
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class FursTestBaza {
static String napaka="";
public static void Test()
{
try
{
String URL = "https://blagajne.fu.gov.si:9003/v1/cash_registers";
System.out.println("Testiranje povezave na: " + URL);
System.setProperty("javax.net.debug", "all");
System.out.println("==================================");
System.out.println("1");
KeyStore p12 = KeyStore.getInstance("pkcs12");
String geslo = "*******"; //private key password
System.out.println("2");
p12.load(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/FURS-AS_davcne_blagajne.p12")), geslo.toCharArray());
Enumeration e = p12.aliases();
String alias = (String) e.nextElement();
System.out.println("alias certifikata: " + alias);
//privatni ključ
Key privateKey = p12.getKey(alias, geslo.toCharArray());
System.out.println("3");
//podpis
Signature podpis = Signature.getInstance("SHA256WithRSA");
podpis.initSign((PrivateKey) privateKey);
System.out.println("4");
//določimo svoj keystore in TLS1.2
SSLContext sslcontext = SSLContext.getInstance("TLSv1.2");
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
KeyStore ks = KeyStore.getInstance("PKCS12");
System.out.println("5");
ks.load(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/FURS-AS_davcne_blagajne.p12")), geslo.toCharArray());
kmf.init(ks, geslo.toCharArray());
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate ca = cf.generateCertificate(new FileInputStream(new File("/oracle/orasw/Wallet/Certifikat/Furs/privateCert/blagajne.fu.gov.si.cer")));
System.out.println("6");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
System.out.println("7");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
System.out.println("8");
TrustManager[] tm = tmf.getTrustManagers();
sslcontext.init(kmf.getKeyManagers(), tm, null);
System.out.println("8.1");
HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext.getSocketFactory());
System.out.println("9");
URL url = new URL(URL);
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url.openConnection();
System.out.println("10");
httpsURLConnection.connect();
System.out.println("Povezan na: " + URL + ", chiper:" + httpsURLConnection.getCipherSuite());
System.out.println("Prekinjam povezavo...");
httpsURLConnection.disconnect();
System.out.println("Povezava zaprta.");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Then have executed this code with PL/SQL:
begin
dbms_java.set_output(500000);
p_test_furs;
end;
The connection from server A works and all works fine, but the problem is on server B.
On server "B" I got exception (above) and If comparing the javax.net.debug
I noticed this exception:
The certificates on both servers are the same.
Java version on my database is the same:
Server A:
select dbms_java.get_ojvm_property(propstring=>'java.version') from dual
returns: 1.6.0_191
Server B:
select dbms_java.get_ojvm_property(propstring=>'java.version') from dual
returns: 1.6.0_191
What can be wrong or what else I can check on the server/database side?