Friday, 14 March 2008

JDBC SSL Demo from JDeveloper Using a Wallet (PKCS12) as a truststore

I decided to test JDBC SSL using a PKCS12 wallet as a truststore to see if I could get this working from JDeveloper here is how I did this:

1. Before trying this I need to be sure I can connect using SQL*Plus and that the database is configured to use TCPS. My SQL*Plus entry was as follows which I used to ensure it was working fine.

SRACANOV-au2_SSL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCPS)(HOST = sracanov-au2.au.oracle.com)(PORT = 2484))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl)
)
)

The sqlnet.ora file is as follows:

SQLNET.AUTHENTICATION_SERVICES=(TCPS,NTS)

SSL_CLIENT_AUTHENTICATION = FALSE

WALLET_LOCATION =
(SOURCE =
(METHOD = FILE)
(METHOD_DATA =
(DIRECTORY = D:\oracle\product\10.2.0\db_1\NETWORK\ADMIN\Wallets\server)
)
)

SSL_CIPHER_SUITES= (SSL_RSA_WITH_AES_128_CBC_SHA, SSL_DH_anon_WITH_3DES_EDE_CBC_SHA)

Now in SQL*Plus we can connect as shown:

$ sqlplus scott/tiger@SRACANOV-au2_SSL

SQL*Plus: Release 10.1.0.4.2 - Production on Fri Mar 14 08:32:38 2008

Copyright (c) 1982, 2005, Oracle. All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SCOTT@SRACANOV-au2_SSL>

With that working we can now move over to the JDBC side and what is required in JDeveloper to get this to work

2. Before we begin because we are using a PKCS12 wallet (ewallet.p12) we have to set the following in our JRE runtime environment file java.security as shown below. I am doing this in my JDeveloper home as that is where I am going to run the client from. Notice how "security.provider.3=oracle.security.pki.OraclePKIProvider" has been added and is third on the list.

#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=oracle.security.pki.OraclePKIProvider
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider

Note: This file would exist in the following location from JDeveloper:

$JDEV_HOME\jdk\jre\lib\security\java.security

3. Now we can start JDeveloper and create a new empty project. In that project we need to add 2 JAR files for our code to compile, one is the 10.2.0.3 JDBC driver file and the other is oraclepki.jar

ojdbc14.jar (10.2.0.3 should be used or later)
$JDEV_HOME\jlib\oraclepki.jar

4. Now add a Java Class as follows, it's referring to the client wallet and some properties which are required to be set, there highlighted in RED.


package pas.jdbc.ssl.demo;

import java.security.Security;

import java.sql.Connection;
import java.sql.SQLException;

import java.sql.*;
import oracle.jdbc.OracleDriver;

public class JDBCSSLTest
{

public JDBCSSLTest()
{
// must enable this
Security.addProvider(new oracle.security.pki.OraclePKIProvider());
}

public void run () throws SQLException
{
Connection conn = getConnection();
System.out.println("Auto Commit = " + conn.getAutoCommit());
conn.close();
}

public static Connection getConnection() throws SQLException
{
String url = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)" +
"(HOST=sracanov-au2.au.oracle.com)(PORT=2484))" +
"(CONNECT_DATA=(SERVICE_NAME=orcl)))";
java.util.Properties props = new java.util.Properties();

props.setProperty("user", "scott");
props.setProperty("password", "tiger");
props.setProperty("javax.net.ssl.trustStore",
"D:\\oracle\\product\\10.2.0\\db_1\\NETWORK\\ADMIN\\" +
"Wallets\\client\\ewallet.p12");
props.setProperty("javax.net.ssl.trustStoreType","PKCS12");
props.setProperty("javax.net.ssl.trustStorePassword","welcome2");

DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection(url, props);
return conn;
}

public static void main(String[] args) throws SQLException
{
JDBCSSLTest dSTest = new JDBCSSLTest();
dSTest.run();
System.out.println("all done..");
}
}



5. Now run the class and verify it is able to establish a connection as follows:

Auto Commit = true
all done..

Few things to note here.

- We must enable Oracle's PKI provider to use wallets as shown below.

// must enable this
Security.addProvider(new oracle.security.pki.OraclePKIProvider());

- The following properties must be set before a connection can be retrieved, and the database username/password are also required along with the wallet password.

props.setProperty("user", "scott");
props.setProperty("password", "tiger");
props.setProperty("javax.net.ssl.trustStore",
"D:\\oracle\\product\\10.2.0\\db_1\\NETWORK\\ADMIN\\" +
"Wallets\\client\\ewallet.p12");
props.setProperty("javax.net.ssl.trustStoreType","PKCS12");
props.setProperty("javax.net.ssl.trustStorePassword","welcome2");

- The connect URL should include a description using TCPS as shown below

"jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)" +
"(HOST=sracanov-au2.au.oracle.com)(PORT=2484))" +
"(CONNECT_DATA=(SERVICE_NAME=orcl)))";

1 comment:

Pas Apicella said...

I found that the following property was required as well.

props.setProperty("oracle.net.ssl_cipher_suites",
"SSL_DH_anon_WITH_3DES_EDE_CBC_SHA, SSL_DH_anon_WITH_RC4_128_MD5, SSL_DH_anon_WITH_DES_CBC_SHA");