Oracle Advanced Security Administrator's Guide
Release 9.0.1

Part Number A90150-01
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Go to previous page Go to next page

E
Oracle Implementation of Java SSL

This appendix describes the Oracle implementation of Java Secure Socket Extension (JSSE), in the following sections:

Prerequisites

To use the Oracle Java SSL implementation, JDK version 1.1 or 1.2 must be installed, and the CLASSPATH environment variable must include the following jar files:

In addition, the Java SSL shared library must be added to the shared library path:

Oracle Java SSL Features

Oracle Java SSL is a commercial-grade implementation of Java Secure Socket Extension (JSSE). In order to create a secure, fast implementation of SSL, Oracle Java SSL uses native code to improve the performance.

In addition to the functionality included in the JSSE specifications, Oracle Java SSL supports the following:

Oracle Java SSL features are described in further detail in the following sections:

SSL Cipher Suites Supported by Oracle Java SSL

Before data can flow through an SSL connection, both sides of the connection must negotiate common algorithms to be used for data transmission. A set of such algorithms combined to provide a mix of security features is called a cipher suite. Selecting a particular cipher suite lets the participants in an SSL connection establish the appropriate level for their communications.

Oracle Java SSL supports cipher suites with the following options:

Certificate and Key Management with Oracle Wallet Manager

You can use Oracle Wallet Manager to generate public/private key pairs and certificate requests. A signed certificate request and the appropriate trusted certificates must be added to produce a complete Oracle wallet.

You can export a complete wallet with a certificate in Ready status, in a BASE64-formatted file, using the menu option Operation ->ExportWallet. This file can be used to add SSL credentials in a Java SSL-based program.

If you are not using Oracle Wallet Manager, you can manually add individual components to a file:

See Also:

 

Security-Aware Applications Support

Some security-aware application do not set trust points. In order to let these applications perform their own validation, Oracle Java SSL lets handshakes complete if no security credentials are set--if a complete certificate chain is sent by the peer. This feature is useful when there is a large number of trust points stored in a database, and the application is constrained from passing all of them to the SSL layer.

Once the handshake is complete, it is possible to obtain the peer certificate chain and extract individual peer certificates. These certificates can be used for application-specific validation, such as matching the certificate's distinguished name (DN) against a user database.

Security-unaware applications that need the trust point check must ensure that trust points are set in the application.

See Also:

Public Class: OracleSSLCredential , for more information about checking peer credentials 

Oracle Java SSL Examples

The examples in this section illustrate the use of Oracle Java SSL. For purposes of the examples, we created a model server and client named SSLServerExample and SSLClientExample, respectively. Together, they demonstrate some common features of Oracle Java SSL, as well as the basics of socket communication. In addition, SSLProxyClientExample demonstrates one of the possible ways to implement firewall tunnelling connections.

We present the complete code for each program, and discuss some of its more important sections.

This example does not cover every feature available in Oracle Java SSL. For more detailed information about different security options available in this package please consult the latter sections of this chapter.

See Also:

 

Oracle Java SSL examples are described in the following sections:

SSLServerExample Program

SSLServerExample is a simple SSL server. It uses a wallet exported from Oracle Wallet Manager to set up its security credentials. When the server is started it waits for a client to initiate a connection. After the SSL handshake is complete, the server sends a short message to the client and closes the connection.

import oracle.security.ssl.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.*;
import javax.net.ssl.*;

public class SSLServerExample 
{

private OracleSSLServerSocketFactoryImpl _socketFactory;
private OracleSSLCredential _credential;
private SSLServerSocket _svrSoc;

private void initCredential(String wltPath, String password) 
throws java.io.IOException 
{
_credential = new OracleSSLCredential();
_credential.setWallet(wltPath, password);
}
private void initSocketFactory() 
throws javax.net.ssl.SSLException
{
_socketFactory 
= (OracleSSLServerSocketFactory)SSLServerSocketFactory.getDefault();
_socketFactory.setSSLProtocolVersion(
OracleSSLProtocolVersion.SSL_Version_3_0_With_2_0_Hello);
_socketFactory.setSSLCredentials(_credential);
}
private void initServerSocket(int port) 
throws java.io.IOException
{
_svrSoc = (SSLServerSocket)_socketFactory.createServerSocket(port);
_svrSoc.setUseClientMode(false);
_svrSoc.setNeedClientAuth(false);
_svrSoc.setEnabledCipherSuites(new String[]{"SSL_RSA_WITH_RC4_128_SHA",
"SSL_RSA_WITH_RC4_128_MD5"});
}
public SSLServerExample(String wltPath, String password, int port)
throws java.io.IOException, javax.net.ssl.SSLException
{
initCredential(wltPath, password);
initSocketFactory();
initServerSocket(port);
}
public void runServer()
{
String message = "Hello! Current Server Time is " + new Date() + "\n";
Socket csocket = null;
OutputStreamWriter out = null;
try
{
csocket = _svrSoc.accept();
out = new OutputStreamWriter(csocket.getOutputStream());
out.write(message);
System.out.println("Connection Succeeded");
}
catch(IOException e)
{
System.out.println("Connection Failed");
e.printStackTrace();
}
finally
{
try
{ 
    if(out != null)
       out.close();
    if(csocket != null)
       csocket.close();
    _svrSoc.close();
}
catch(IOException e){}
}
}
public static void main(String[] argv)
{
System.getProperties().put("SSLServerSocketFactoryImplClass",
"oracle.security.ssl.OracleSSLServerSocketFactoryImpl");
try
{
SSLServerExample myServer = new SSLServerExample("mywallet.txt",
    "welcome1", 19978);
myServer.runServer();
}
catch(IOException i)
{
System.out.println("Failied to start up server");
i.printStackTrace();
}
}
}

Initializing the Credentials:

SSLServerExample uses a wallet created by Oracle Wallet Manager, so the job of setting up the credential object is quite easy. In initCredential() we call

_credential = new OracleSSLCredential();
_credential.setWallet(wltPath, password);

to read the wallet located at wltPath. The private key, user certificate, certificate and trust points located in the wallet are used in the connection. An IOException is thrown if an error occurs while accessing the wallet.

If you do not elect to use the wallet, you can install the necessary security credentials manually.

See Also:

Public Class: OracleSSLCredential for more information about:

  • addTrustedCert()

  • addCertChain()

  • setPrivateKey()

 

Initializing the Socket Factory:

To create SSL sockets, you must access the proper socket factory. For Oracle Java SSL, oracle.security.ssl.OracleSSLSocketFactoryImpl is the name of the class that implements javax.net.ServerSocketFactory. In order to make sure we access it correctly we must set up the System Properties in the main() function using

System.getProperties().put("SSLServerSocketFactoryImplClass","oracle.security.ss
l.OracleSSLServerSocketFactoryImpl");


Once the system properties are set, we can obtain an instance of the socket factory and customize it. In initSocketFactory() we specify the SSL protocol the sockets created by this factory are to support, and install the security credentials to be used by all sockets created by this factory.

Initializing Server Socket:

The method initServerSocket() uses the socket factory to create a new server socket that listens in server mode on the specified port:

_svrSoc = (SSLServerSocket)_socketFactory.createServerSocket(port);
_svrSoc.setUseClientMode(false);


Once the socket is created, we can change some of its attributes:

_svrSoc.setNeedClientAuth(false);
_svrSoc.setEnabledCipherSuites(new String[]{"SSL_RSA_WITH_RC4_128_SHA"
"SSL_RSA_WITH_RC4_128_MD5"});


For this example we do not require the clients to authenticate themselves to the server. However, instead of using the default enabled cipher suites, we only let those clients connect that support RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5 cipher suites.

Use OracleSSLServerSocketFactory.getSupportedCipherSuites() to determine which cipher suites are supported by Java SSL.

See Also:

 

Waiting for the Connection and Sending Data:

SSLServerExample waits until the client connects to the server. Notice that the method accept() blocks until a connection is established. Once the client connects we obtain the output stream for the socket by calling getOutputStream(). We use this output stream to send information to the client. When the server has no more data to send to the client, the server closes the corresponding output stream and socket. In order to stop accepting connections, the server must close the corresponding server socket. The server closes the ServerSocket when it cannot accept any further connections.

See Also:

Java documentation about their java.net package, for information about sockets and socket streams. 

SSLClientExample Program

The SSLClientExample is a simple program (JDK1.1) used to connect to the SSLServerExample program. Notice that the initilization of the SSLClientExample is very similar to that of the server. However, certain differences have been included in this example to demonstrate some of the features of JavaSSL. The explanations focus on these differences whenever appropriate:

import oracle.security.ssl.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.*;
import javax.net.ssl.*;
import javax.security.cert.*;

public class SSLClientExample 
{

protected OracleSSLSocketFactoryImpl _socketFactory;
private OracleSSLCredential _credential;
protected SSLSocket _socket;
private void initCredential(String wltPath, String password)
throws java.io.IOException
{
_credential = new OracleSSLCredential();
_credential.setWallet(wltPath, password);
}
private void initSocketFactory() 
throws javax.net.ssl.SSLException
{
_socketFactory 
= (OracleSSLSocketFactoryImpl)SSLSocketFactory.getDefault();
_socketFactory.setSSLProtocolVersion(
OracleSSLProtocolVersion.SSL_Version_3_0);
_socketFactory.setSSLCredentials(_credential);
}

private void initSocket(String host, int port) 
throws java.io.IOException
{
_socket = (SSLSocket)_socketFactory.createSocket(host, port);
_socket.setUseClientMode(true);
}

public SSLClientExample(String wltPath, String pass, String host, int port)
throws java.io.IOException, javax.net.ssl.SSLException
{
initCredential(wltPath, pass);
initSocketFactory();
initSocket(host, port);
}

public void connectSocket()
{
try
{
_socket.startHandshake();
getData();
}
catch(IOException e)
{
System.out.println("Connection Failed");
e.printStackTrace();
}
finally
{
try
{
    _socket.close();
} 
catch(IOException e){}
}
}

public void getData()
{
InputStreamReader in = null;
try
{
int ch;
SSLSession session = _socket.getSession();

System.out.println("Negotiated Cipher Suite " +
    session.getCipherSuite());
X509Certificate[] peerCerts = session.getPeerCertificateChain();
for(int i = 0; i < peerCerts.length; i++)
{
    System.out.println(peerCerts[i]);
}
System.out.println("Server Response:");
in = new InputStreamReader(_socket.getInputStream());
ch =  in.read();
while((char)ch != '\n')
{
    if(ch != -1)
    System.out.print((char)ch);
    ch=in.read();
}
System.out.println();
}
catch(IOException e)
{
System.out.println("Connection Failed");
e.printStackTrace();
}
finally
{ 
try
{ 
    if(in != null)
    in.close();
}
catch(IOException e){}
}
}
    
public static void main(String[] argv)
{
System.getProperties().put("SSLSocketFactoryImplClass", 
"oracle.security.ssl.OracleSSLSocketFactoryImpl");
try
{
SSLClientExample myClient = new 
SSLClientExample("mywallet.txt","welcome1","localhost", 19978);
myClient.connectSocket();
}
catch(IOException i)
{
System.out.println("Failied to start up client");
i.printStackTrace();
}
}
}


Note:

For JDK1.2, change import javax.security.cert.*; to import java.security.cert.*; 


Initializing the Credentials:

The client intializes the credentials in the same way as the server. For purposes of the example, the client and the server use the same wallet. However, in real life applications the client and the server must have different security credentials. In order for an SSL connection to complete successfully it is important that the proper trusted certificates are present in the wallets.

See Also:

Chapter 16, Using Oracle Wallet Manager, for more information about trusted certificates 

Initializing the Socket Factory:

The socket factory class used to create client sockets is similar to the one used by the server. Once again it is necessary to set the system properties in order to obtain the correct socket factory before configuring it in initSocketFactory(). The correct socket factory is set in main()using:

System.getProperties().put("SSLSocketFactoryImplClass",
"oracle.security.ssl.OracleSSLSocketFactoryImpl");

Initializing and Connecting the Client Socket:

Client sockets are created by the socket factory just as server sockets are created by the server socket factory. However, in order to connect the client socket to a specific server, we supply the server's name and the port number at creation. In addition, we ensure that the socket connects in client mode:

_socket = (SSLSocket)_socketFactory.createSocket(host, port);
_socket.setUseClientMode(true);

Once the socket is created it can connect to the server using:

_socket.startHandshake();

Viewing Peer Credentials:

After the socket connects to the server, information about the connection can be accessed. The information is stored in the OracleSSLSession class, an instance of which can be obtained using _socket.getSession().

In our program we print out the cipher suite negotiated between the client and the server as well as the security credentials of the server. This information can be used by security-aware applications to determine whether it should trust the connection. For example, most browsers check to confirm that the common name in the server certificate matches the URL that was accessed, and they display a warning if it does not. However, this check is not required by the SSL protocol.

Receiving Data:

Receiving and sending data through an SSL Socket is no different than receiving data through any other socket. In this example we access the socket's input stream, and proceed to read until an end-of-line character occurs.

See Also:

Java documentation about their java.net package, for information about sockets and socket streams. 

SSLProxyClientExample Program

SSLProxyClientExample uses firewall tunneling to establish a secure connection to the server. Please note that this program might not work for all firewalls. For example, some firewalls do not permit a connection to non-standard ports, such as port 19978 that is used here. In this case you have to set up a secure server on port 443 and modify the client appropriately.

import oracle.security.ssl.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.net.*;
import javax.net.ssl.*;
import javax.security.cert.*;

public class SSLProxyClientExample extends SSLClientExample 
{

private String _proxyName;
private int _proxyPort;
    
protected void initSocket(String host, int port) 
throws java.io.IOException
{
final String connString = "CONNECT" + host + ":" + port + 
" HTTP/1.0 \n" + "User-Agent: Oracle Proxy Enabled SSL Socket\n\n";
Socket normalSocket = new Socket(_proxyName, _proxyPort);
OutputStreamWriter out 
= new OutputStreamWriter(normalSocket.getOutputStream());
out.write(connString, 0, connString.length());
_socket = (SSLSocket)_socketFactory.createSocket(normalSocket);
}

public SSLProxyClientExample(String wltPath, String password,String host,
                                 int port, String proxyName, int proxyPort)
throws java.io.IOException, javax.net.ssl.SSLException
{
super(wltPath, password, host, port);
_proxyName = proxyName;
_proxyPort = proxyPort;
}

public static void main(String[] argv)
{
System.getProperties().put("SSLSocketFactoryImplClass", 
"oracle.security.ssl.OracleSSLSocketFactory");
try{
SSLClientExample myClient 
    = new SSLProxyClientExample("mywallet.txt", "welcome1",
    "localhost", 19978,  "www-proxy", 80);
myClient.connectSocket();
}
catch(IOException i)
{
System.out.println("Failied to start up client");
i.printStackTrace();
}
}
}


Note:

For JDK1.2, change import javax.security.cert.*; to import java.security.cert.*; 


Initializing and Connecting the Client Socket:

The only significant difference between SSLProxyClientExample and its superclass, SSLClientExample, lies in the method initSocket(). In order to set up a tunnelling connection it is necessary to create a plain socket. This socket is used to send a special message, connString,to the firewall, setting up the connection to the actual server. Once this connection is set up, we can use the plain socket to initialize an SSL Socket using:

_socketFactory.createSocket(normalSocket)

Typical Errors

This section describes some typical Java SSL errors.

SSLException X509CertExpiredErr

Problem

During the handshake the program fails with SSLException and message X509CertExpiredErr. The program worked yesterday, and no changes were made.

Solution

Your user certificate has expired. You must obtain a new user certificate.

See Also:

Chapter 16, Using Oracle Wallet Manager 

SSLException X509CertChainInvalidErr

Problem

The handshake fails on the client side with SSLException and message X509CertChainInvalidErr. A web browser can connect to the server successfully.

Solution

Either your server or your client does not have the proper credentials. If the client program sets trusted certificates, you must ensure that the list includes at least one of the certificates in the server's certificate chain. In addition you must ensure that the server sends the complete certificate chain to the client--as Java SSL cannot build the certificate chain itself. If you are using an Apache server, you must set the variables SSLCertificateChainFile and SSLCertificateFile correctly. This is especially important if the client program does not set trusted certificates.

For more information consult your web server documentation.

Client Connection with No Credentials

Problem

Server lets client connect even though no OracleSSLCredentials are set in the client program.

Solution

In order to enable security-aware applications to perform their own validation, Java SSL permits a connection if no credentials are set by the client, if the server sends a complete certificate chain. To avoid this behavior, your application must set at least one trusted certificate.

See Also:

Public Class: OracleSSLCredential 

Oracle Java SSL API

This section describes the public classes and interfaces used in Oracle Java SSL. Since Oracle Java SSL is an implementation of JSSE, only the Oracle additions to the JSSE package are described.

This section describes the following Oracle Java SSL classes and interfaces:

Public Class: OracleSSLCredential

This public class extends java.lang.Object.

Credentials are used to authenticate the server and the client to each other. OracleSSLCredential is used to load user certificates, trusted certificates (trust points), and private keys from base64 or der encoded certificates.

Constructor

public OracleSSLCredential()

Methods

public void addTrustedCert(java.lang.String b64TrustedCert)

public void addTrustedCert(byte[] trustedCert)

public void setPrivateKey(java.lang.String b64PvtKey,
java.lang.String password)

public void setPrivateKey(byte[] pvtKey,
java.lang.String password)

public void addCertChain(java.lang.String b64certChainCert)

public void addCertChain(byte[] certChainCert)

public void setWallet(java.lang.String wltPath,
java.lang.String password) throws java.io.IOException

Public Interface: OracleSSLProtocolVersion

This interface defines the available SSL protocol versions.

Fields

public static final int SSL_Version_Undetermined

public static final int SSL_Version_3_0_With_2_0_Hello

public static final int SSL_Version_3_0_Only

public static final int SSL_Version_2_0

public static final int SSL_Version_3_0

Public Class: OracleSSLServerSocketFactoryImpl

This public class extends javax.net.ssl.SSLServerSocketFactory; it is used to create SSL server sockets.

This class implements javax.net.ssl.SSLServerSocketFactory methods that are needed to create server sockets. In addition it provides extra methods, described bellow, that are necessary to configure options specific to Oracle Java SSL.

Constructor

public OracleSSLServerSocketFactoryImpl()

Methods

public void setSSLCredentials(OracleSSLCredential
sslCredential)throws javax.net.ssl.SSLException

public void setSSLProtocolVersion(int version)
throws javax.net.ssl.SSLException

Public Class: OracleSSLSession

This public class extends java.lang.Object; implements javax.net.ssl.SSLSession.

This class implements most methods specified in javax.net.ssl.SSLSession. However, the following methods have not been implemented: getPeerHost(), getValue(), invalidate(), removeValue(), and getValueNames(). This class provides extra methods, described bellow, that are specific to Oracle Java SSL.

Methods

public byte[][] getPeerRawCertificateChain()
throws javax.net.ssl.SSLPeerUnverifiedException

public java.lang.String getNegotiatedProtocolVersion()

Public Class: OracleSSLSocketFactoryImpl

This public class extends javax.net.ssl.SSLSocketFactory.

This class implements javax.net.ssl.SSLSocketFactory methods that are needed to create server sockets. In addition it provides extra methods, described below, that are necessary to configure options specific to Oracle Java SSL.

Constructor

public OracleSSLSocketFactoryImpl()

Methods

public java.net.Socket createSocket(java.net.Socket socket)
throws java.io.IOException

public void setSSLCredentials(OracleSSLCredential
sslCredential)throws javax.net.ssl.SSLException

public void setSSLProtocolVersion(int version)
throws javax.net.ssl.SSLException


Go to previous page Go to next page
Oracle
Copyright © 1996-2001, Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback