Oracle® Containers for J2EE Security Guide
10g Release 3 (10.1.3) B14429-01 |
|
![]() Previous |
![]() Next |
This chapter describes the OC4J implementation of HTTPS that provides Secure Sockets Layer functionality to client HTTP connections. This includes using Oracle HTTPS with standard Java Secure Socket Extension (JSSE) features. The following topics are included:
Note: Secure communication between a client and Oracle HTTP Server is independent of secure communication between Oracle HTTP Server and OC4J. (Also note that the secure AJP protocol used between Oracle HTTP Server and OC4J is not visible to the end user.) This chapter covers only secure communication between OC4J and the client.This chapter assumes that you have already obtained keys and certificates. For general information about configuring OC4J to use the Secure Sockets Layer, see Chapter 11, "Integration with SSL and ORMIS". Standalone OC4J supports SSL communication directly between a client and OC4J, using HTTPS. This is discussed in "Using SSL with Standalone OC4J". |
HTTPS is vital to securing client/server interactions. For many server applications, HTTPS is handled by the Web server. However, any application that acts as a client, such as servlets that initiate connections to other Web servers, needs its own HTTPS implementation to make requests and to receive information securely from the server. Java application developers who are familiar with either the HTTPClient
package or the Sun Microsystems java.net
package can easily use Oracle HTTPS to secure client interactions with a server.
Oracle HTTPS has functionality based on the HTTPConnection
class of the HTTPClient
package, which provides a complete HTTP client library. To support client HTTPS connections, several methods have been added to the HTTPConnection
class that use the OracleSSL class, OracleSSLCredential
.
Important: The Oracle implementation ofHTTPClient has diverged from the original open source version upon which it was based. The Oracle version should be considered as a distinct product. Even though there are still many similarities, the two are not necessarily compatible with each other.
|
Note: OracleHTTPClient supports two different SSL implementations: JSSE and OracleSSL. This documentation discusses the two implementations separately.
|
See Also:
|
The HTTPConnection
class is used to create new connections that use HTTP, with or without SSL. To provide support for PKI (public key infrastructure) digital certificates and wallets, the methods described in "Oracle HTTPS Example" have been added to this class.
See Also:
|
Security credentials are used to authenticate the server and the client to each other. Oracle HTTPS uses the Oracle Java SSL package, OracleSSLCredential
, to load user certificates and trustpoints from base64 or DER-encoded certificates. (DER, part of the X.690 ASN.1 standard, stands for Distinguished Encoding Rules.)
The API for Oracle Java SSL requires that security credentials be passed to the HTTP connection before the connection is established. The OracleSSLCredential
class is used to store these security credentials. Typically, a wallet generated by Oracle Wallet Manager is used to populate the OracleSSLCredential
object. Alternatively, individual certificates can be added by using an OracleSSLCredential
class API. After the credentials are complete, they are passed to the connection with the setCredentials()
method.
Oracle HTTPS supports HTTP 1.0 and HTTP 1.1 connections between a client and a server. To provide SSL functionality, new methods have been added to the HTTPConnection
class of this package. These methods are used in conjunction with Oracle Java SSL to support cipher suite selection, security credential management with Oracle Wallet Manager, security-aware applications, and other features that are described in the following sections. Oracle HTTPS uses the Oracle Java SSL class, OracleSSLCredential
, and it extends the HTTPConnection
class of the HTTPClient
package. HTTPClient
supports two SSL implementations, OracleSSL and JSSE.
In addition to the functionality included in the HTTPClient
package, Oracle HTTPS supports the following:
Multiple cryptographic algorithms
Certificate and key management with Oracle Wallet Manager
Limited support for the java.net.URL
framework
Both the OracleSSL and JSSE SSL implementations
In addition, Oracle HTTPS uses the HTTPClient
package to support:
HTTP tunneling through proxies
HTTP proxy authentication
The following sections describe Oracle HTTPS features in detail:
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.
HTTPClient
supports the OracleSSL and JSSE SSL implementations, each of which supports a number of cipher suites.
The rest of this section discusses the following topics:
In general, you should prefer:
RSA to Diffie-Hellman, because RSA defeats many security attacks
3DES or RC4 128 to other encryption methods, because 3DES and RC4 128 have strong keys
SHA1 digest to MD5, because SHA1 produces a stronger digest
OracleSSL supports the cipher suites listed in Table 12-1. Note that with NULL encryption, SSL is used only for authentication and data-integrity purposes.
Table 12-1 Cipher Suites Supported by OracleSSL
Cipher Suite | Authentication | Encryption | Hash Function (Digest) |
---|---|---|---|
|
RSA |
3DES EDE CBC |
SHA1 |
|
RSA |
RC4 128 |
SHA1 |
|
RSA |
RC4 128 |
MD5 |
|
RSA |
DES CBC |
SHA1 |
|
RSA |
RC4 40 |
MD5 |
|
RSA |
DES40 CBC |
SHA1 |
|
DH anon |
3DES EDE CBC |
SHA1 |
|
DH anon |
RC4 128 |
MD5 |
|
DH anon |
DES CBC |
SHA1 |
|
DH anon |
RC4 40 |
MD5 |
|
DH anon |
DES40 CBC |
SHA1 |
|
RSA |
NULL |
SHA1 |
|
RSA |
NULL |
MD5 |
JSSE supports the cipher suites listed in Table 12-2. Note that with NULL encryption, SSL is used only for authentication and data integrity purposes.
Table 12-2 Cipher Suites Supported by JSSE
Cipher Suite | Authentication | Encryption | Hash Function (Digest) |
---|---|---|---|
|
RSA |
3DES EDE CBC |
SHA1 |
|
RSA |
RC4 128 |
SHA1 |
|
RSA |
RC4 128 |
MD5 |
|
RSA |
DES CBC |
SHA1 |
|
RSA |
RC4 40 |
MD5 |
|
DH anon |
3DES EDE CBC |
SHA1 |
|
DH anon |
RC4 128 |
MD5 |
|
DH anon |
DES CBC |
SHA1 |
|
DH anon |
RC4 40 |
MD5 |
|
DH anon |
DES40 CBC |
SHA1 |
|
RSA |
NULL |
SHA1 |
|
RSA |
NULL |
MD5 |
|
DH |
DES CBC |
SHA1 |
|
DH |
3DES EDE CBC |
SHA1 |
|
DH |
DES40 CBC |
SHA1 |
Users can access information regarding established SSL connections using the getSSLSession()
method in the HTTPConnection
class of the Oracle HTTPClient
package. After a connection is established, users can retrieve the cipher suite used for the connection, the peer certificate chain, and other information about the current connection.
Oracle HTTPS uses Oracle Java SSL to provide security-aware applications support. When security-aware applications do not set trust points, Oracle Java SSL allows them to perform their own validation, letting the handshake complete successfully only if a complete certificate chain is sent by the peer. When applications authenticate to the trustpoint level, they are responsible for authenticating individual certificates below the trustpoint.
After the handshake is complete, the application must obtain the SSL session information and perform any additional validation for the connection.
Security-unaware applications that require the trust point check must ensure that trust points are set in the HTTPS infrastructure.
See Also:
|
The HTTPClient
package provides basic support for the java.net.URL
framework with the HTTPClient.HttpUrlConnection
class. However, many of the Oracle HTTPS features are supported through system properties only.
Features that are supported only through system properties are:
Cipher suites selection option
Confidentiality-only option
Server authentication option
Mutual authentication option
Security credential management with Oracle Wallet Manager
Note: If thejava.net.URL framework is used, set the java.protocol.handler.pkgs system property to select the HTTPClient package as a replacement for the JDK client, as follows:
java.protocol.handler.pkgs=HTTPClient |
See Also:
|
For many users of HTTPS it is desirable to specify some default properties in a non-programmatic way. The best way to accomplish this is through Java system properties which are accessible through the java.lang.System
class. These properties are the only way for users of the java.net.URL
framework to set security credential information. Oracle HTTPS recognizes the following properties:
The following sections describe how to set these properties.
This property can be set to point to the text wallet file exported from Oracle Wallet Manager that contains the credentials that are to be used for a specific connection. For example:
javax.net.ssl.KeyStore=/etc/ORACLE/WALLETS/Default/default.txt
Where default.txt
is the name of the text wallet file that contains the credentials.
If no other credentials have been set for the HTTPS connection, then the file indicated by this property is opened when a handshake first occurs. If any errors occur while reading this file, then the connection fails and an IOException
is thrown.
If you do not set this property, the application is responsible for verifying that the certificate chain contains a certificate that can be trusted. However, HTTPClient
using Oracle SSL does verify that all of the certificates in the certificate chain, from the user certificate to the root CA, have been sent by the server and that all of these certificates contain valid signatures.
This property can be set to the password that is necessary to open the wallet file. For example:
javax.net.ssl.KeyStorePassword=welcome1
Where welcome1
is the password that is necessary to open the wallet file.
Storing the wallet file password as a Java system property can result in a security risk in some environments. To avoid this risk, use one of the following alternatives:
If mutual authentication is not required for the application, use a text wallet that contains no private key. No password is needed to open these wallets.
If a password is necessary, then do not store it in a clear text file. Instead, load the property dynamically before the HTTPConnection
is started by using System.setProperty()
. Unset the property after the handshake is completed.
For OracleSSL, this property can be set to a comma-delimited list of cipher suites. For example:
Oracle.ssl.defaultCipherSuites= SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_WITH_RC4_128_MD5
The cipher suites that you set this property to are used as the default cipher suites for new HTTPS connections.
The following is a simple program that uses Oracle HTTPS, HTTPClient
, and OracleSSL to connect to a Web server, send a GET
request, and fetch a Web page. The complete code for this program is presented here followed by sections that explain how Oracle HTTPS is used to set up secure connections.
import HTTPClient.HTTPConnection; import HTTPClient.HTTPResponse; import oracle.security.ssl.OracleSSLCredential; import java.io.IOException; public class HTTPSConnectionExample { public static void main(String[] args) { if(args.length < 4) { System.out.println( "Usage: java HTTPSConnectionTest [host] [port] " + "[wallet] [password]"); System.exit(-1); } String hostname = args[0].toLowerCase(); int port = Integer.decode(args[1]).intValue(); String walletPath = args[2]; String password = args[3]; HTTPConnection httpsConnection = null; OracleSSLCredential credential = null; try { httpsConnection = new HTTPConnection("https", hostname, port); } catch(IOException e) { System.out.println("HTTPS Protocol not supported"); System.exit(-1); } try { credential = new OracleSSLCredential(); credential.setWallet(walletPath, password); } catch(IOException e) { System.out.println("Could not open wallet"); System.exit(-1); } httpsConnection.setSSLCredential(credential); try { httpsConnection.connect(); } catch (IOException e) { System.out.println("Could not establish connection"); e.printStackTrace(); System.exit(-1); } javax.servlet.request.X509Certificate[] peerCerts = null; try { peerCerts = (httpsConnection.getSSLSession()).getPeerCertificateChain(); } catch(javax.net.ssl.SSLPeerUnverifiedException e) { System.err.println("Unable to obtain peer credentials"); System.exit(-1); } String peerCertDN = peerCerts[peerCerts.length -1].getSubjectDN().getName(); peerCertDN = peerCertDN.toLowerCase(); if(peerCertDN.lastIndexOf("cn="+ hostname) == -1) { System.out.println("Certificate for " + hostname + " is issued to " + peerCertDN); System.out.println("Aborting connection"); System.exit(-1); } try { HTTPResponse rsp = httpsConnection.Get("/"); System.out.println("Server Response: "); System.out.println(rsp); } catch(Exception e) { System.out.println("Exception occured during Get"); e.printStackTrace(); System.exit(-1); } } }
This example uses a wallet created by Oracle Wallet Manager to set up credential information.
First, create the credentials and load the wallet:
mycredential = new OracleSSLCredential(); mycredential.setWallet(wallet_path, password);
After the credentials are created, pass them to your HTTPConnection
instance (here called httpsConnection
) through its setSSLCredential()
method. This method takes the OracleSSLCredential
instance, created in the first step, as input:
httpsConnection.setSSLCredential(mycredential);
The private key, user certificate, and trust points located in the wallet can now be used for the connection.
Although SSL verifies that the certificate chain presented by the server is valid and contains at least one certificate trusted by the client, that does not prevent impersonation by malicious third parties. An HTTPS standard that addresses this problem requires that HTTPS servers have certificates issued to their host name. Then it is the responsibility of the client to perform this validation after the SSL connection is established.
To perform this validation in this sample program, HTTPSConnectionExample
establishes a connection to the server without transferring any data, as follows:
httpsConnection.connect();
After the connection is established, the connection information, in this case the server certificate chain, is obtained as follows:
peerCerts = (httpsConnection.getSSLSession()).getPeerCertificateChain();
Finally the server certificate common name is obtained as follows:
String peerCertDN = peerCerts[peerCerts.length -1].getSubjectDN().getName(); peerCertDN = peerCertDN.toLowerCase();
If the certificate name is not the same as the host name used to connect to the server, then the connection is aborted as follows:
if(peerCertDN.lastIndexOf("cn="+ hostname) == -1) { System.out.println("Certificate for " + hostname + " is issued to " + peerCertDN); System.out.println("Aborting connection"); System.exit(-1); }
It is important to verify the connection information before data is transferred from the client or from the server. The data transfer is performed in the same way for HTTPS as it is for HTTP. In this sample program a GET
request is made to the server as follows:
HTTPResponse rsp = httpsConnection.Get("/");
Oracle Application Server supports HTTPS client connections using the Java Secure Socket Extension (JSSE). A client can configure HTTPClient
to use JSSE as the underlying SSL provider as follows:
Create a truststore using the keytool.
Set the truststore property. A client wishing to use JSSE must specify the client truststore location through the javax.net.ssl.trustStore
property. Unlike OracleSSL, the client is not required to set the javax.net.ssl.keyStore
property.
Obtain the JSSE SSL socket factory (javax.net.ssl.SSLSocketFactory
instance) by calling the static SSLSocketFactory.getDefault()
method.
Create an HTTPClient
connection (HTTPConnection
instance).
Configure the HTTPClient
connection to use the JSSE implementation of SSL. HTTPClient
can be configured to use JSSE in either of the following ways:
(For each connection) The client calls the following method on the HTTPConnection
instance, specifying the JSSE SSL socket factory retrieved by the getDefault()
method in step 3:
void setSSLSocketFactory(SSLSocketFactory factory)
In this case, the SSL socket factory is set for only this connection instance. Example 12-1 below demonstrates this technique.
(Entire VM) The client calls the following static method on the HTTPConnection
class:
void HttpConnection.setDefaultSSLSocketFactory(SSLSocketFactory factory)
In this case, the SSL socket factory is set for all connection instances in the Java VM, until the method is called again with a different setting. This method must be called before instantiating any HTTPConnection
instances that are to be affected.
Call HTTPConnection.connect()
before sending any HTTPS data. This allows the connection to verify the SSL handshaking that must occur between client and server before any data can be encrypted and sent.
Use the HTTPConnection
instance normally. At this point, the client is set up to use HTTPClient
with JSSE. There is no additional configuration necessary and basic usage is the same.
Example 12-1 Using JSSE with HTTPClient
public void obtainHTTPSConnectionUsingJSSE() throws Exception { // set the trust store to the location of the client's trust store file // this value specifies the certificate authorities the client accepts System.setProperty("javax.net.ssl.trustStore", KEYSTORE_FILE); // creates the HTTPS URL URL testURL = new URL("https://" + HOSTNAME + ":" + HTTPS_PORTNUM); // call SSLSocketFactory.getDefault() to obtain the default JSSE implementation // of an SSLSocketFactory SSLSocketFactory socketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault(); HTTPConnection connection = new HTTPConnection(testURL); // configure HTTPClient to use JSSE as the underlying // SSL provider connection.setSSLSocketFactory(socketFactory); // call connect to setup SSL handshake try { connection.connect(); } catch (IOException e) { e.printStackTrace(); } HTTPResponse response = connection.Get("/index.html"); }
Notes:
|
See Also:
|