1

I have configured a Oracle 11g database server to work with SSL using a wallet and self signed certificate. Tested it with local client (sqlplus) and it works without any issues. Now I'm trying to connect the database using Java JDBC. Currently I'm getting an error:

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to
find valid certification path to requested target

Here is my code:

public static void main(String[] args)
{
    Connection connection = null;

    String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=192.168.200.191)(PORT=1522))(CONNECT_DATA=(SERVICE_NAME=VDB)))";

    Properties props = new Properties();
    props.setProperty("user", "dbuser");
    props.setProperty("password", "dbpass");
    props.setProperty("oracle.net.ssl_cipher_suites","(SSL_RSA_WITH_3DES_EDE_CBC_SHA)");

    /* Load the database driver */
    try
    {
        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        connection = DriverManager.getConnection(url,props);
        if (connection != null) {
            System.out.println("You made it, take control your database now!");
        } else {
            System.out.println("Failed to make connection!");
        }
    }
    catch (SQLException ex) {
       ex.printStackTrace();
    }
}

I did some more research, and found that if the wallet is configured as 'auto_login', I can try the following:

   Connection connection = null;

   String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=192.168.200.191)(PORT=1522))(CONNECT_DATA=(SERVICE_NAME=VDB)))";

    Properties props = new Properties();
    props.setProperty("user", "dbuser");
    props.setProperty("password", "dbpass");
    props.setProperty("javax.net.ssl.trustStore", "C:\\oracle\\wallet\\cwallet.sso");
    props.setProperty("javax.net.ssl.trustStoreType","SSO");

    /* Load the database driver */
    try
    {
        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        connection = DriverManager.getConnection(url,props);
        if (connection != null) {
            System.out.println("You made it, take control your database now!");
        } else {
            System.out.println("Failed to make connection!");
        }
    }
    catch (SQLException ex) {
    ex.printStackTrace();
}

In this case, I'm getting:

java.security.NoSuchAlgorithmException: SSO KeyStore not available

I've added 3 Jars: oraclepki.jar, osdt_cert.jar, osdt_core.jar Attempted to run the last version of the code, getting exception:

java.lang.ClassNotFoundException: com.phaos.crypto.AuthenticationException

Perhaps I should specify the wallet location? as I did in the tnsnames.ora file? or specify the certificate CN?

Please advise, thanks.

David Faizulaev
  • 4,651
  • 21
  • 74
  • 124

4 Answers4

1

Using services or resources that requires certificates within your application, require that you somehow trust the certificate issuer or certificate itself. In this case, I guess you will have to trust the certificate itself as it is self-signed and not issued by a well-known CA (already trusted by the trust-store bundled with the JRE you're using).

In order to do this, export the certificate that you use together with your database and locate a file called "cacerts". The file exists within your jdk-installation folder. Example:

/path/to/jdk/jre/lib/security/cacerts

The easiest thing to do, is just to import the certificate to this file (you can use some commands to do this, or if you're lazy like me - download KSE and click the Import-button: http://keystore-explorer.org/). You may also specify your own trust-store using properties mentioned here:

https://docs.oracle.com/cd/E19830-01/819-4712/ablqw/index.html

If you choose to use a custom trust-store, you have more control regarding the cacerts - as if you're choosing to update to a newer jdk installation, that installation will use the cacerts issued with the jdk :-).

Anyway. Hope it helped a bit.

vegaasen
  • 1,022
  • 7
  • 16
1

Found the solution, as I'm using SSO need to specify both keystore and truststore.

        Connection connection = null;
    String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=192.168.200.191)(PORT=1522))(CONNECT_DATA=(SERVICE_NAME=NNVSDB)))";

    Properties props = new Properties();
    props.setProperty("user", "dbuser");
    props.setProperty("password", "dbpass");

    //Single sign on
    props.setProperty("javax.net.ssl.trustStore", "C:\\oracle\\wallet\\cwallet.sso");
    props.setProperty("javax.net.ssl.trustStoreType","SSO");
    props.setProperty("javax.net.ssl.keyStore","C:\\oracle\\wallet\\cwallet.sso");
    props.setProperty("javax.net.ssl.keyStoreType","SSO");
    props.setProperty("oracle.net.authentication_services","(TCPS)");

    /* Load the database driver */
    try
    {
        Security.addProvider(new oracle.security.pki.OraclePKIProvider());
        DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
        connection = DriverManager.getConnection(url,props);
        if (connection != null) {
            System.out.println("You made it, take control your database now!");
        } else {
            System.out.println("Failed to make connection!");
        }
    }
    catch (SQLException ex) {
    ex.printStackTrace();
}
David Faizulaev
  • 4,651
  • 21
  • 74
  • 124
0

The JVM tries to establish a chain of trust of the server's certificate towards any known trusted CAs. You can either obtain a certificate from a CA which is trusted by your Java's default TrustStore or you can provide your own CA certificate (the one you used to sign the self-signed certificate) to your JVM by generating your own TrustStore. You would then pass the TrustStore e.g. using the command line argument -Djavax.net.ssl.trustStore= when starting your application.

Keep in mind that passing a custom TrustStore requires you to either add all CAs which are contained in your JRE's default TrustStore or you live with the fact that no chains of trust can be established to any certificates not issued by your own CA.

A third option is adding your own CA certificate to your system's global TrustStore which leads to any Java application accepting certificates from your CA. This is a shortcut but might not be in your best interest if you require a strict separation of CAs.

oschlueter
  • 2,596
  • 1
  • 23
  • 46
  • Should I generate a TrustStore for the server certificate only? or client & server certificate? In addition, I need another jar except for the ojdbc6.jar? – David Faizulaev Dec 22 '16 at 11:44
  • If your client needs to authenticate using a client certificate you'd put that in a KeyStore (which is the same kind of file but it serves a different purpose). In your TrustStore you'd only need the certificate(s) required to establish a chain of trust for the server certificate (which is like an ID card the server presents to your client). So in your case the required certificate to establish said chain of trust is the CA certificate used to sign your server's certificate. – oschlueter Dec 22 '16 at 11:48
  • My server certificate is self-signed, so I just need to import it to the TrustStore? – David Faizulaev Dec 22 '16 at 11:53
  • You have at least two certificates in play: your self-signed server certificate and another certificate used to sign the server certificate. You need to import the latter one into the TrustStore. – oschlueter Dec 22 '16 at 13:15
  • I did not use any certificate to sign the server certificate, this is the command I used: orapki wallet add -wallet "C:\oracle\wallet" -pwd WalletPasswd123 -dn "CN=DBSERVER" -keysize 1024 -self_signed -sign_alg sha256 -validity 3650 – David Faizulaev Dec 22 '16 at 13:18
0

I think below link may be helpful to you.

http://docs.oracle.com/cd/B19306_01/java.102/b14355/sslthin.htm#BABHFBJD

bugfix
  • 57
  • 9
  • I've added the following props.setProperty("oracle.net.wallet_location", "(SOURCE=(METHOD=file)(METHOD_DATA=(DIRECTORY=c:\\oracle\\wallet)))"); And now I get: "java.sql.SQLException: PKI classes not found. To use 'connect /' functionality, oraclepki.jar must be in the classpath: java.lang.NoClassDefFoundError: oracle/s ecurity/pki/OracleWallet" Do I need another jar possibly? – David Faizulaev Dec 22 '16 at 11:41
  • Actually, I have not implemented this type of feature. I Just found one article in google and I read it. So,I think it might help you. So, I give you. – bugfix Dec 23 '16 at 08:00