Oracle8i Enterprise JavaBeans Developer's Guide and Reference Release 3 (8.1.7) Part Number A83725-01 |
Library | Service | Contents | Index

## Client-side Authentication

The Oracle data server is a secure server; a client application cannot access data stored in the database without first being authenticated by the database server. Oracle8i CORBA server objects and Enterprise JavaBeans execute in the database server. For a client to activate such an object and invoke methods on it, the client must authenticate itself to the server. The client authenticates itself when a CORBA or EJB object starts a new session. The following are examples of how each IIOP client must authenticate itself to the database:

- When a client initially starts a new session, it must authenticate itself to the database.

- When a client passes an object reference (a CORBA IOR or an EJB bean handle) to a second client, the second client connects to the session specified in the object reference. The second client authenticates itself to the server.

The client authenticates itself by providing one of the following types:

Authentication type | Definition
--- | ---
Certificates | You can provide the user certificate, the Certificate Authority certificate (or a chain that contains both, including other identifying certificates), and a private key.
Username and password combination | You can provide the username and password through either credentials or the login protocol. In addition, you can pass a database role to the server, along with the username and password.

The type of client-side authentication can be determined by the server's configuration. If, within the SQLNET.ORA file, the `SSL_CLIENT_AUTHENTICATION` parameter is `TRUE`, the client must provide certificate-based authentication. If `SSL_CLIENT_AUTHENTICATION` is `FALSE`, the client authenticates itself with a username/password combination. If `SSL_CLIENT_AUTHENTICATION` is `TRUE` and the client provides a username/password, the connection handshake will fail.

The following table gives a brief overview of the options that the client has for authentication.

- The columns represent the options available if you have chosen to use SSL for data integrity.

- The rows demonstrate the three authentication vehicles: login protocol, credentials, and certificates.

- The table entries detail the different methods you must employ when implementing the client-side authentication type.

  Authentication vehicle | NON-SSL transport | SSL transport
  --- | --- | ---
  Providing username and password using the login protocol | Implicit method: Set JNDI property to NON_SSL_LOGIN; provide username and password in JNDI properties. Explicit method: Create a Login object with username and password. | Implicit method: Set JNDI property to SSL_LOGIN; provide username and password in JNDI properties. Explicit method: Create a Login object with username and password.
  Providing username and password using credentials | Not supported because the password would transmit in the clear. | Set JNDI property to SSL_CREDENTIAL; username and password are implicitly sent to the server in the handshake.
  Providing certificates | Not supported because certificates require an SSL transport. | Set JNDI property to SSL_CLIENT_AUTH; provide client certificate, CA certificate, and private key in JNDI properties. Pure CORBA objects use `AuroraCertificateManager` class to specify certificates, CA certificate, and private key.

As the table demonstrates, most of the authentication options include setting an appropriate value in JNDI properties.

### Using JNDI for Authentication

To set up client-side authentication using JNDI, you set the `javax.naming.Context.SECURITY_AUTHENTICATION` attribute to one of the following values:

- `ServiceCtx.NON_SSL_LOGIN`--A plain IIOP connection is used. Because SSL is not used, all data flowing over the line is not encrypted. Thus, to protect the password, the client uses the login protocol to authenticate itself. In addition, the server does not provide SSL certificates to the client to identify itself.

- `ServiceCtx.SSL_LOGIN`--An SSL-enabled IIOP connection is used. All data flowing over the transport is encrypted. If you do not want to provide a certificate for the client authentication, use the login protocol to provide the username and password.

  Because this is an SSL connection, the server sends its certificate identity to the client. The client is responsible for verifying the server's certificate, if interested, for server authentication. Optionally, the client can set up trust points for the server's certificate to be verified against.

- `ServiceCtx.SSL_CREDENTIAL`--An SSL-enabled IIOP connection is used. All data flowing over the transport is encrypted. The client provides the username and password without using the login protocol for client authentication to the server. The username and password are automatically passed to the server in a security context, on the first message.

  Note: The client's password is not encrypted, as it is with SSL. It might be slightly more efficient than SSL_LOGIN, where encrypting a password over an SSL connection is redundant.

  The server provides its certificate identity to the client. The client is responsible for verifying the server's certificate, if interested, for server authentication.

- `ServiceCtx.SSL_CLIENT_AUTH`--An SSL-enabled IIOP connection is used. All data flowing over the transport is encrypted. The client provides appropriate certificates for client-side authentication to the server. In addition, the server provides its certificate identity to the client. If interested, the client is responsible for authorizing the server's certificate.

- Nothing is specified. The client must activate the login protocol explicitly before activating and invoking methods on a server-side object. Use this method when a client must connect to an existing session and invoke methods on an existing object. See the `demo/examples/corba/session/sharedsession` example for more information. The username and password in the initial context environment are automatically passed as parameters to the login object's `authenticate()` method.

Within each of these options, you choose to do one or more of the following:

Client authentication | authenticate itself to the server using login protocol authenticate itself to the server using straight username and password authenticate itself to the server using SSL certificates
Server authentication | authenticate itself to the client using SSL certificates

For information on how to implement each of these methods for client or server authentication, see the following sections:

- Providing Username and Password for Client-Side Authentication

- Using Certificates for Client Authentication

- Server-Side Authentication

### Providing Username and Password for Client-Side Authentication

The client authenticates itself to the database server either through a username/password or by supplying appropriate certificates. The username/password can be supplied either through Oracle's login protocol or credentials over the SSL transport connection.

- Provide a username and password by setting JNDI properties, which implicitly sets these values in a login protocol. Set `SECURITY_AUTHENTICATION` to `ServiceCtx.SSL_LOGIN` or `ServiceCtx.NON_SSL_LOGIN`.

- Provide a username and password through credentials. The username and password are provided implicitly and are shipped to the server over the encrypted SSL transport. Set `SECURITY_AUTHENTICATION` to `serviceCtx.SSL_CREDENTIAL`.

- Provide a username and password in an explicitly activated login protocol.

  Note: The `Login` class serves as an implementation of the client side of the login handshaking protocol and as a proxy object for calling the server login object. This component is packaged in the `aurora_client.jar` file. All Oracle8i ORB applications must import this library.

#### Username Sent by Setting JNDI Properties for the Login Protocol

A client can use the login protocol to authenticate itself to the Oracle8i data server. You can use the login protocol either with or without SSL encryption, because a secure handshaking encryption protocol is built in to the login protocol.

If your application requires an SSL connection for client-server data security, specify the SSL_LOGIN service context value for the SECURITY_AUTHENTICATION property that is passed when the JNDI initial context is obtained. The following example defines the connection to be SSL-enabled for the login protocol. Notice that the username and password are set.

    Hashtable env = new Hashtable();
    env.put(javax.naming.Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
    env.put(javax.naming.Context.SECURITY_PRINCIPAL, username);
    env.put(javax.naming.Context.SECURITY_CREDENTIALS, password);
    env.put(javax.naming.Context.SECURITY_AUTHENTICATION, ServiceCtx.SSL_LOGIN);
    Context ic = new InitialContext(env);
    ...

If your application does not use an SSL connection, specify NON_SSL_LOGIN within the SECURITY_AUTHENTICATION parameter as shown below:

Note: The login handshaking is secured by encryption, but the remainder of the client-server interaction is not secure.

    env.put(javax.naming.Context.SECURITY_AUTHENTICATION, ServiceCtx.NON_SSL_LOGIN);

When you specify values for all four JNDI Context variables--URL_PKG_PREFIXES, SECURITY_PRINCIPAL, SECURITY_CREDENTIALS, and SECURITY_AUTHENTICATION--the first invocation of the `Context.lookup()`method performs a login automatically.

If the client setting up the connection is not using JNDI look up because it already has an IOR, the user that gave them the IOR for the object should have also passed in a Login object that exists in the same session as the active object. You must provide the username and password in the `authenticate` method of the Login object, before invoking the methods on the active object.

##### Logging In and Out of the JServer Session

If the session owner wishes to exit the session, the owner can use the `logout` method of the `LogoutServer` object, which is pre-published as "`/etc/logout`". You use the `LogoutServer` object to exit the session. Only the session owner is allowed to logout. Any other owner receives a NO_PERMISSION exception.

The `LogoutServer` object is analogous to the `LoginServer` object, which is pre-published as "`/etc/login`". You can use the `LoginServer` object to retrieve the `Login` object, which is used to authenticate to the server. This is an alternative method to using the `Login` object within the JNDI lookup.

The following example shows how a client can authenticate using the `LoginServer` object and can exit the session through the `LogoutServer` object.

    import oracle.aurora.AuroraServices.LoginServer;
    import oracle.aurora.AuroraServices.LogoutServer;
    ...
    // To log in using the LoginServer object
    LoginServer loginServer = (LoginServer)ic.lookup(serviceURL + "/etc/login");
    Login login = new Login(loginServer);
    System.out.println("Logging in ..");
    login.authenticate(user, password, null);
    ...
    //To logout using the LogoutServer
    LogoutServer logout = (LogoutServer)ic.lookup(serviceURL + "/etc/logout");
    logout.logout();

#### Username Sent Implicitly by using Credentials

Using the `ServiceCtx.SSL_CREDENTIAL` authentication type means that the username, password, and, potentially, a role are passed to the server on the first request. Because this information is passed over an SSL connection, the password is encrypted by the transfer protocol, and there is no need for the handshaking that the Login protocol uses. This is slightly more efficient and is recommended for SSL connections.

#### Username Sent by Explicitly Activating a Login Object

You can explicitly create and populate a Login object for the database login. Typically, you would do this if you wanted to create and use more than a single session from a client. The following example shows a client creating and logging on to two different sessions. To do this, you must perform the following steps:

1. Create the initial context.

2. Perform a look up on a URL for the destination database.

3. On this database service context, create two subcontexts--one for each session.

4. Login to each session using a Login object, providing a username and password.

   Note: The username and password for both sessions are identical because the destination database is the same database. If the client were to connect to two different databases, the username and password may need to be different for logging on.

       // Prepare a simplified Initial Context as we are going to do

       // everything by hand
       Hashtable env = new Hashtable ();
       env.put (Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
       Context ic = new InitialContext (env);

       // Get a SessionCtx that represents a database instance
       ServiceCtx service = (ServiceCtx)ic.lookup (serviceURL);

       // Create and authenticate a first session in the instance.
       SessionCtx session1 = (SessionCtx)service.createSubcontext (":session1");
       LoginServer login_server1 = (LoginServer)session1.activate ("etc/login");
       Login login1 = new Login (login_server1);
       login1.authenticate (user, password, null);

       // Create and authenticate a second session in the instance.
       SessionCtx session2 = (SessionCtx)service.createSubcontext (":session2");
       LoginServer login_server2 = (LoginServer)session2.activate ("etc/login");
       Login login2 = new Login (login_server2);
       login2.authenticate (user, password, null);

       // Activate one Hello object in each session
       Hello hello1 = (Hello)session1.activate (objectName);
       Hello hello2 = (Hello)session2.activate (objectName);

### Using Certificates for Client Authentication

Client authentication through certificates requires the client sending a certificate or certificate chain to the server; the server verifies that the client is truly who the client said it was and that it is trusted.

Note: All certificates, trustpoints, and the private key should be in base-64 encoded format.

You set up the client for certificate authentication through one of the following methods:

- Specifying Certificates in a File

- Specifying Certificates in Individual JNDI Properties

- Specifying Certificates using AuroraCertificateManager

#### Specifying Certificates in a File

You can set up a file that contains the user certificate, the issuer certificate, the entire certificate chain, an encrypted private key, and the trustpoints. Once created, you can specify that the client use the file during connection handshake for client authentication.

1. Create the client certificate file--This file can be created through an export feature in the Wallet Manager. The Oracle Wallet Manager has an option that creates this file. You must populate a wallet using the Wallet Manager before requesting that the file is created.

   After you create a valid wallet, bring up the Wallet Manager and perform the following:

   - From the menu bar pull down, click on Operations > Export Wallet.

   - Within the filename field, enter the name that you want the certificate file known as.

   This creates a base-64 encoded file that contains all certificates, keys, and trustpoints that you added within your wallet. For information on how to create the wallet, see the Oracle Advanced Security Administrator's Guide.

2. Specify the client certificates file for the connection--Within the client code, set the `SECURITY_AUTHENTICATION` property to `ServiceCtx.SSL_CLIENT_AUTH`. Provide the appropriate certificates and trustpoints for the server to authenticate against. Specify the filename and decrypting key in the JNDI properties, as follows:

   Values | Set in JNDI Property
   --- | ---
   Name of the certificate file | `SECURITY_PRINCIPAL`
   Key for decrypting the private key | `SECURITY_CREDENTIAL`

   The following code is an example of how to set up the JNDI properties to define the client certificate file:

       Hashtable env = new Hashtable();
       env.put(javax.naming.Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
       env.put(javax.naming.Context.SECURITY_PRINCIPAL, <filename>);
       env.put(javax.naming.Context.SECURITY_CREDENTIAL, <decrypting_key>);
       env.put(javax.naming.Context.SECURITY_AUTHENTICATION,

       	ServiceCtx.SSL_CLIENT_AUTH);
       Context ic = new InitialContext(env);
       ...

   For example, if your decrypting key is `welcome12` and the certificate file is `credsFile`, the following two lines would specify these values within the JNDI context:

       env.put(Context.SECURITY_CREDENTIALS, "welcome12");
       env.put(Context.SECURITY_PRINCIPAL, "credsFile");

#### Specifying Certificates in Individual JNDI Properties

You can provide each certificate, private key, and trust point programmatically, by setting each item individually within JNDI properties. Once you populate the JNDI properties with the user certificate, issuer (Certificate Authority) certificate, encrypted private key, and trust points, they are used during connection handshake for authentication. To identify client-side authentication, set the `SECURITY_AUTHENTICATION` property to `serviceCtx.SSL_CLIENT_AUTH`.

Note: Only a single issuer certificate can be set through JNDI properties.

You can choose any method for setting up your certificates within the JNDI properties. All authorization information values must be set up before initializing the context.

The following example declares the certificates as a static variable. However, this is just one of many options. Your certificate must be base-64 encoded. For example, in the following code, the `testCert_base64` is a base-64 encoded client certificate declared as a static variable. The other variables for CA certificate, private key, and so on, are not shown, but they are defined similarly.

Note: When setting individual certificates as static variables, any certificates for Oracle8i parties do not have any separators. However, if you are setting a certificate for a Visigenic ORB (as the client callback object does in a callback scenario), the certificate must be delineated by "BEGIN CERTIFICATE" and "END CERTIFICATE" identifying lines. See the Visigenic documentation for the format of these strings.

    final private static String testCert_base64 =
      "MIICejCCAeOgAwIBAgICAmowDQYJKoZIhvcNAQEEBQAwazELMAkGA1UEBhMCVVMx" +
      "DzANBgNVBAoTBk9yYWNsZTEoMCYGA1UECxMfRW50ZXJwcmlzZSBBcHBsaWNhdGlv" +
      "biBTZXJ2aWNlczEhMB8GA1UEAxMYRUFTUUEgQ2VydGlmaWNhdGUgU2VydmVyMB4X" +
      "DTk5MDgxNzE2MjIxMloXDTAwMDIxMzE2MjIxMlowgYUxCzAJBgNVBAYTAlVTMRsw" +
      "GQYDVQQKExJPcmFjbGUgQ29ycG9yYXRpb24xPDA6BgNVBAsUMyoqIFNlY3VyaXR5" +
      "IFRFU1RJTkcgQU5EIEVWQUxVQVRJT04gT05MWSB2ZXJzaW9uMiAqKjEbMBkGA1UE" +
      "AxQSdGVzdEB1cy5vcmFjbGUuY29tMHwwDQYJKoZIhvcNAQEBBQADawAwaAJhANG1" +
      "Kk2K7uOOtI/UBYrmTe89LVRrG83Eb0/wY3xWGelkBeEUTwW57a26u2M9LZAfmT91" +
      "e8Afksqc4qQW23Sjxyo4ObQK3Kth6y1NJgovBgfMu1YGtDHaSn2VEg8p58g+nwID" +
      "AQABozYwNDARBglghkgBhvhCAQEEBAMCAMAwHwYDVR0jBBgwFoAUDCHwEuJfIFXD" +
      "a7tuYNO8bOw1EYwwDQYJKoZIhvcNAQEEBQADgYEARC5rWKge5trqgZ18onldinCg" +
      "Fof6D/qFT9b6Cex5JK3a2dEekg/P/KqDINyifIZL0DV7z/XCK6PQDLwYcVqSSK/m" +
      "487qjdH+zM5X+1DaJ+ROhqOOX54UpiAhAleRMdLT5KuXV6AtAx6Q2mc8k9bzFzwq" +
      "eR3uI+i5Tn0dKgxhCZU=\n";

    Hashtable env = new Hashtable();
    env.put(Context.URL_PKG_PREFIXES, "oracle.aurora.jndi");
    env.put(Context.SECURITY_AUTHENTICATION, ServiceCtx.SSL_CLIENT_AUTH);
    //decrypting key
    env.put(Context.SECURITY_CREDENTIALS, "welcome12");

    // you may also set the certificates individually, as shown bellow.
    //User certificate
    env.put(ServiceCtx.SECURITY_USER_CERT, testCert_base64);
    //Certificate Authority's certificate
    env.put(ServiceCtx.SECURITY_CA_CERT, caCert_base64);
    //Private key
    env.put(ServiceCtx.SECURITY_ENCRYPTED_PKEY, encryptedPrivateKey_base64);
    // setup the trust point
    env.put(ServiceCtx.SECURITY_TRUSTED_CERT, trustedCert);

    Context ic = new InitialContext(env);

#### Specifying Certificates using AuroraCertificateManager

CORBA clients that do not use JNDI can use `AuroraCertificateManager` for setting the user and issuer certificates, the encrypted private key, and the trust points.

`AuroraCertificateManager` maintains certificates for your application. For the certificates to be passed on the SSL handshake for the connection, you must set the certificates before an SSL connection is made. Setting up a certificate in this manner is only required if the following is true:

- The client sets its certificates through `AuroraCertificateManager` if client-side authentication is required, and the client does not want to use JNDI properties for setting certificates.

- The server sets its certificates through `AuroraCertficateManager` if it is executing a callout or a callback. The typical server-side authentication for a simple client/server exchange is taken care of by the database wallet. However, if this server intends to act as a client by executing a callout or callback, it needs to set certificates identifying itself; it cannot use the database certificate that is contained in the wallet.

### AuroraCertificateManager Class

The methods offered by this object allow you to:

- Set the SSL protocol version. The default is Undetermined.

- Set the private key and certificate chain.

- Require that client applications authenticate themselves by presenting their certificate chain. This method is used only by servers.

Invoking the `ORB.resolve_initial_references` method with the parameter `SSLCertificateManager` will return an object that can be narrowed to a `AuroraCertificateManager`. Example 6-1 shows a code example of the following methods.

#### addTrustedCertificate

This method adds the specified certificate as a trusted certificate. The certificate must be in DER encoded format. The client adds trustpoints through this method for server-side authentication.

When your client wants to authenticate a server, the server sends its certificate chain to the client. You might not want to check every certificate in the chain. For example, you have a chain composed of the following certificates: Certificate Authority, enterprise, business unit, a company site, and a user. If you trust the company site, you would check the user's certificate, but you might stop checking the chain when you get to the company site's certificate, because you accept the certificates above the company sites in the hierarchical chain.

Syntax

    void addTrustedCertificate(byte[] derCert);

Parameter | Description
--- | ---
derCert | The DER encoded byte array containing the certificate.

#### requestClientCertificate

This method is invoked by servers that wish to require certificates from client applications. This method is not intended for use by client applications.

Note: The `requestClientCertificate` method is not currently required, because the SQLNET.ORA and LISTENER.ORA configuration parameter SSL_CLIENT_AUTHENTICATION performs its function.

Syntax

    void requestClientCertificate(boolean need);

Parameter | Description
--- | ---
need | If true, the client must send a certificate for authentication. If false, no certificate is requested from the client.

#### setCertificateChain

This method sets the certificate chain for your client application or server object and can be invoked by clients or by servers. The certificate chain always starts with the Certificate Authority certificate. Each subsequent certificate is for the issuer of the preceding certificate. The last certificate in the chain is the certificate for the user or process.

Syntax

    void setCertificateChain(byte[][] derCertChain)

Parameter | Description
--- | ---
derCertChain | A byte array containing an array of certificates.

#### setEncryptedPrivateKey

This method sets the private key for your client application or server object. You must specify the key in PKCS5 or PKCS8 format.

Syntax

    void setEncryptedPrivateKey(byte[] key, String password);

Parameter | Description
--- | ---
key | The byte array that contains the encrypted private key.
password | A string containing a password for decrypting the private key.

#### setProtocolVersion

This method sets the SSL protocol version that can be used for the connection. A 2.0 Client trying to establish an SSL connection with a 3.0 Server will fail and the converse. We recommend using Version_Undetermined, because it lets the peers establish an SSL connection whether they are using the same protocol version or not. `SSL_Version_Undetermined` is the default value.

Syntax

    void setProtocolVersion(int protocolVersion);

Parameter | Description
--- | ---
protocolVersion | The protocol version being specified. The value you supply is defined in `oracle.security.SSL.OracleSSLProtocolVersion`. This class defines the following values: `SSL_Version_Undetermined`: Version is undetermined. This is used to connect to SSL 2.0 and SSL 3.0 peers. This is the default version. `SSL_Version_3_0_With_2_0_Hello`: Not supported. `SSL_Version_3_0`: Used to connect to 3.0 peers only. `SSL_Version_2_0`: Not supported.

#### Example 6-1 Setting SSL Security Information Using AuroraCertificateManager

This example does the following:

1. Retrieve the `AuroraCertificateManager``.`

2. Initialize this client's SSL information:

   1. Set the certificate chain through `setCertificateChain`.

   2. Set the trustpoint through addTrustedCertificate.

   3. Set the private key through `setEncryptedPrivateKey`.

          // Get the certificate manager
          AuroraCertificateManager cm = AuroraCertificateManagerHelper.narrow(
          	orb.resolve_initial_references("AuroraSSLCertificateManager"));

          BASE64Decoder decoder = new BASE64Decoder();
          byte[] userCert = decoder.decodeBuffer(testCert_base64);
          byte[] caCert = decoder.decodeBuffer(caCert_base64);

          // Set my certificate chain, ordered from CA to user.
          byte[][] certificates = {
                  caCert, userCert
          };
          cm.setCertificateChain(certificates);
          cm.addTrustedCertificate(caCert);

          // Set my private key.
          byte[] encryptedPrivateKey =
          decoder.decodeBuffer(encryptedPrivateKey_base64);

          cm.setEncryptedPrivateKey(encryptedPrivateKey, "welcome12");

| Copyright © 1996-2000, Oracle Corporation. All Rights Reserved. |
Library | Service | Contents | Index