15 CertPath Providers

The WebLogic Security service provides a framework that finds and validates X509 certificate chains for inbound 2-way SSL, outbound SSL, application code, and WebLogic Web services. The Certificate Lookup and Validation (CLV) framework is a new security plug-in framework that finds and validates certificate chains. The framework extends and completes the JDK CertPath functionality, and allows you to create a custom CertPath provider.

The following sections provide the background information you need to understand before adding certificate lookup and validation capability to your custom security providers, and provide step-by-step instructions for adding certificate lookup and validation capability to a custom security provider:

Certificate Lookup and Validation Concepts

A CertPath is a JDK class that stores a certificate chain in memory. The term CertPath is also used to refer to the JDK architecture and framework that is used to locate and validate certificate chains.

There are two distinct types of providers, CertPath Validators and CertPath Builders:

  • The purpose of a certificate validator is to determine if the presented certificate chain is valid and trusted. As the CertPath Validator provider writer, you decide how to validate the certificate chain and determine whether you need to use the trusted CA's.

  • The purpose of a certificate builder is to use a selector (which holds the selection criteria for finding the CertPath) to find a certificate chain. Certificate builders often to validate the certificate chain as well. As the CertPath Builder provider writer, you decide which of the four selector types you support and whether you also validate the certificate chain. You also decide how much of the certificate chain you fill in and whether you need to use the trusted CA's.

The WebLogic CertPath providers are built using both the JDK and WebLogic CertPath SPI's.

The Certificate Lookup and Validation Process

The certificate lookup and validation process is shown in Figure 15-1.

Figure 15-1 Certificate Lookup and Validation Process

Description of Figure 15-1 follows
Description of "Figure 15-1 Certificate Lookup and Validation Process"

Do You Need to Implement Separate CertPath Validators and Builders?

You can implement the CertPath provider in several ways:

  • You can implement a CertPath Builder that performs both building and validation. In this case, you are responsible for:

    1. Implementing the Validator SPI.

    2. Implementing the Builder SPI.

    3. You must validate the certificate chain you build as part of the Builder SPI. Your provider will be called only once; you will not be called a second time specifically for validation.

    4. You decide the validation algorithm, which selectors to support, and whether to use trusted CA's.

  • You can implement a CertPath Validator that performs only validation. In this case, you are responsible for:

    1. Implementing the Validator SPI.

    2. You decide the validation algorithm and whether to use trusted CA's.

  • You can implement a CertPath Builder that performs only building. In this case, you are responsible for:

    1. Implementing the Builder SPI.

    2. You decide whether to validate the chain you build.

    3. You decide which selectors to support and whether to use trusted CA's.

CertPath Provider SPI MBeans

WebLogic Server includes two CertPath provider SPI MBeans, both of which extend CertPathProviderMBean:

  • CertPathBuilderMBean indicates that the provider can look up certificate chains. It adds no attributes or methods. CertPathBuilder providers must implement a custom MBean that extends this MBean.

  • CertPathValidatorMBean indicates that the provider can validate a certificate chain. It adds no attributes or methods. CertPathValidator providers must implement a custom MBean that extends this MBean.

Your CertPath provider, depending on its type, must extend one or both of the MBeans. A security provider that supports both building and validating should write an MBean that extends both of these MBeans, as shown in Example 15-1.

Example 15-1 Sample CertPath MBean MDF

<?xml version="1.0" ?>
<!DOCTYPE MBeanType SYSTEM "commo.dtd">

<MBeanType
Name          = "MyCertPathProvider"
DisplayName   = "MyCertPathProvider"
Package       = "com.acme"
Extends       = "weblogic.management.security.pk.CertPathBuilder"
Implements    = "weblogic.management.security.pk.CertPathValidator"
PersistPolicy = "OnUpdate"
>
<MBeanAttribute
Name          = "ProviderClassName"
Type          = "java.lang.String"
Writeable     = "false"
Default       = "&quot;com.acme.MyCertPathProviderRuntimeImpl&quot;"
/>

<MBeanAttribute
Name          = "Description"
Type          = "java.lang.String"
Writeable     = "false"
Default       = "&quot;My CertPath Provider&quot;"
/>

<MBeanAttribute
Name          = "Version"
Type          = "java.lang.String"
Writeable     = "false"
Default       = "&quot;1.0&quot;"
/>

 <!-- add custom attributes for the configuration data needed by this provider -->
<MBeanAttribute
Name          = "CustomConfigData"
Type          = "java.lang.String"
/>

WebLogic CertPath Validator SSPI

The WebLogic CertPath Validator SSPI has four parts:

WebLogic CertPath Builder SSPI

The WebLogic CertPath Builder SSPI has four parts:

Relationship Between the WebLogic Server CertPath SSPI and the JDK SPI

Unlike other WebLogic Security Framework providers, your implementation of the CertPath provider relies on a tightly-coupled integration of WebLogic and JDK interfaces. This integration might best be shown in the tasks you perform to create a CertPath provider.

If you are writing a CertPath Validator, you must perform the following tasks:

  1. Create a CertPathValidatorMBean that extends CertPathProviderMBean, as described in Generate an MBean Type Using the WebLogic MBeanMaker.

  2. Implement the JDK java.security.cert.CertPathValidatorSpi, as described in Implement the JDK CertPathBuilderSpi and/or CertPathValidatorSpi Interfaces.

    Your JDK implementation will be passed a JDK CertPathParameters object that you can cast to a WebLogic CertPathValidatorParametersSpi. You can then access its WebLogic methods to get the trusted CA's and ContextHandler. You can also use it to access your WebLogic CertPath provider object.

    Use the CertPathValidatorParametersSpi to provide the data you need to validate the certificate chain, such as Trusted CA's, the ContextHandler, and your CertPath provider SSPI implementation, which gives access to any custom configuration data provided by your MBean, as described in Use the CertPathValidatorParametersSpi SSPI in Your CertPathValidatorSpi Implementation.

    Your WebLogic CertPath provider is important because your CertPathValidatorSpi implementation has no direct way to get the custom configuration data in your MBean. Your WebLogic CertPath provider can provide a proprietary mechanism to make your custom MBean data available to your JDK implementation.

  3. Implement the WebLogic CertPath provider SSPI, as described in Implement the CertPath Provider SSPI. In particular, you use the initialize method of the CertPath provider SSPI to hook into the MBean and make its custom configuration data available to your CertPathValidatorSpi implementation, as shown in Example 15-2.

  4. Implement a JDK security provider that registers your CertPathValidatorSpi implementation, as described in Implement the JDK Security Provider SPI. This coding might not be intuitive, and is called out in Example 15-5.

If you are writing a CertPath Builder, you must perform the following tasks:

  1. Create a CertPathBuilderMBean that extends CertPathProviderMBean, as described in Generate an MBean Type Using the WebLogic MBeanMaker.

  2. Implement the JDK java.security.cert.CertPathBuilderSpi, as described in Implement the JDK CertPathBuilderSpi and/or CertPathValidatorSpi Interfaces.

    Your JDK implementation will be passed a JDK CertPathParameters object that you can cast to a WebLogic CertPathBuilderParametersSpi. You can then access its WebLogic methods to get the trusted CA's, selector, and ContextHandler. You can also use it to access your WebLogic CertPath provider object.

    Use the CertPathBuilderParametersSpi to provide the data you need to build the CertPath, such as Trusted CA's, ContextHandler, the CertPathSelector, and your CertPath provider SSPI implementation, which gives access to any custom configuration data provided by your MBean, as described in Use the CertPathBuilderParametersSpi SSPI in Your CertPathBuilderSpi Implementation.

    Your WebLogic CertPath provider is important because your CertPathBuilderSpi implementation has no direct way to get the custom configuration data in your MBean. Your WebLogic CertPath provider can provide a proprietary mechanism to make your custom MBean data available to your JDK implementation.

  3. Implement a WebLogic CertPath provider SSPI, as described in Implement the CertPath Provider SSPI. In particular, you use the initialize method of the CertPath provider SSPI to hook into the MBean and make its custom configuration data available to your CertPathBuilderSpi implementation, as shown in Example 15-2.

  4. Implement the JDK security provider that registers your CertPathBuilderSpi implementation, as described in Implement the JDK Security Provider SPI. This coding might not be intuitive, and is called out in Example 15-5.

Do You Need to Develop a Custom CertPath Provider?

WebLogic Server includes a CertPath provider and the Certificate Registry.

The WebLogic Server CertPath provider is both a CertPath Builder and a CertPath Validator. The provider completes certificate paths and validates the certificates using the trusted CA configured for a particular WebLogic Server instance. It can build only chains that are self-signed or are issued by a self-signed certificate authority, which must be listed in the server's trusted CA's. If a certificate chain cannot be completed, it is invalid. The provider uses only the EndCertificateSelector selector.

The WebLogic Server CertPath provider also checks the signatures in the chain, ensures that the chain has not expired, and checks that one of the certificates in the chain is issued by one of the trusted CAs configured for the server. If any of these checks fail, the chain is not valid. Finally, the provider checks each certificate's basic constraints (that is, the ability of the certificate to issue other certificates) to ensure the certificate is in the proper place in the chain.

The WebLogic Server CertPath provider can be used as a CertPath Builder and a CertPath Validator in a security realm.

The WebLogic Server Certificate Registry is an out-of-the-box CertPath provider that allows the administrator to configure a list of trusted end certificates via the Administration Console. The Certificate Registry is a builder/validator. The selection criteria can be EndCertificateSelector, SubjectDNSelector, IssuerDNSerialNumberSelector, or SubjectKeyIdentifier. The certificate chain that is returned has only the end certificate. When it validates a chain, it makes sure only that the end certificate is registered; no further checking is done.

You can configure both the CertPath provider and the Certificate Registry. You might do this to make sure that a certificate chain is valid only if signed by a trusted CA, and that the end certificate is in the registry.

If the supplied WebLogic Server CertPath providers do not meet your needs, you can develop a custom CertPath provider.

How to Develop a Custom CertPath Provider

If the WebLogic CertPath provider or Certificate Registry does not meet your needs, you can develop a custom CertPath provider by following these steps:

Create Runtime Classes Using the Appropriate SSPIs

Before you start creating runtime classes, you should first:

When you understand this information and have made your design decisions, create the runtime classes for your custom CertPath provider by following these steps:

Implement the JDK CertPathBuilderSpi and/or CertPathValidatorSpi Interfaces

The java.security.cert.CertPathBuilderSpi interface is the Service Provider Interface (SPI) for the CertPathBuilder class. All CertPathBuilder implementations must include a class that implements this interface (CertPathBuilderSpi).

The java.security.cert.CertPathValidatorSpi interface is the Service Provider Interface (SPI) for the CertPathValidator class. All CertPathValidator implementations must include a class that implements this interface (CertPathValidatorSpi).

Example 15-6 shows an example of implementing the CertPathBuilderSpi and CertPathValidatorSpi interfaces.

Implement the CertPath Provider SSPI

The CertPathProvider SSPI interface exposes the services provided by both the JDK CertPathValidator and CertPathBuilder SPIs and allows the provider to be manipulated (initialized, started, stopped, and so on).

In particular, you use the initialize method of the CertPath provider SSPI to hook into the MBean and make its custom configuration data available to your CertPathBuilderSpi or CertPathValidatorSpi implementation, as shown in Example 15-2.

A more complete example is available in Example 15-6.

Example 15-2 Code Fragment: Obtaining Custom Configuration Data From MBean

public class MyCertPathProviderRuntimeImpl implements CertPathProvider
{
:
:
   public void initialize(ProviderMBean mBean, SecurityServices securityServices)
   {
     MyCertPathProviderMBean myMBean = (MyCertPathProviderMBean)mBean;
     description = myMBean.getDescription();
     customConfigData = myMBean.getCustomConfigData();
:
}
:
   // make my config data available to my JDK CertPathBuilderSpi and    
   // CertPathValidatorSpi impls
   private String getCustomConfigData() { return customConfigData; }
}
:
static public class MyJDKCertPathBuilder extends CertPathBuilderSpi
{
:
//get my runtime implementation instance which holds the configuration
//data needed to build and validate the cert path
MyCertPathProviderRuntimeImpl runtime =
(MyCertPathProviderRuntimeImpl)params.getCertPathProvider();
String myCustomConfigData = runtime.getCustomConfigData();

Example 15-5 shows how to register your JDK implementation with the JDK.

To implement the CertPathProvider SSPI, provide implementations for the methods described in Understand the Purpose of the "Provider" SSPIs and the following methods:

  • getCertPathBuilder

    public CertPathBuilder getCertPathBuilder()
    

    Gets a CertPath Provider's JDK CertPathBuilder that invokes your JDK CertPathBuilderSpi implementation, as shown in Example 15-3. A CertPathBuilder finds, and optionally validates, a certificate chain.

Example 15-3 Code Fragment: getCertPathBuilder

public void initialize(ProviderMBean mBean, SecurityServices securityServices)   
{
:
     // get my JDK cert path impls
     try {
       certPathBuilder = CertPathBuilder.getInstance(BUILDER_ALGORITHM);
     } catch (NoSuchAlgorithmException e) { throw new AssertionError("..."); }
  • getCertPathValidator

    public CertPathValidator getCertPathValidator()
    

    Gets a CertPath Provider's JDK CertPathValidator that invokes your JDK CertPathValidatorSpi implementation, as shown in Example 15-4. A CertPathValidator validates a certificate chain.

Example 15-4 Code Fragment: getCertPathValidator

public void initialize(ProviderMBean mBean, SecurityServices securityServices)   
{
:
     // get my JDK cert path impls
     try {
       certPathValidator = CertPathValidator.getInstance(VALIDATOR_ALGORITHM);
     } catch (NoSuchAlgorithmException e) { throw new AssertionError("..."); }
   }

Implement the JDK Security Provider SPI

Implement the JDK security provider SPI and use it to register your CertPathBuilderSpi or CertPathValidatorSpi implementations with the JDK. Use it to register your JDK implementation in your provider's initialize method.

Example 15-6 shows an example of creating the runtime class for a sample CertPath provider. Example 15-5 shows the fragment from that larger example that implements the JDK security provider.

Example 15-5 Implementing the JDK Security Provider

public class MyCertPathProviderRuntimeImpl implements CertPathProvider
{
private static final String MY_JDK_SECURITY_PROVIDER_NAME = "MyCertPathProvider";
private static final String BUILDER_ALGORITHM = MY_JDK_SECURITY_PROVIDER_NAME + "CertPathBuilder";
private static final String VALIDATOR_ALGORITHM = MY_JDK_SECURITY_PROVIDER_NAME + "CertPathValidator";
:
:
   public void initialize(ProviderMBean mBean, SecurityServices securityServices)
   {
     MyCertPathProviderMBean myMBean = (MyCertPathProviderMBean)mBean;

     description = myMBean.getDescription();

     customConfigData = myMBean.getCustomConfigData();

// register my cert path impls with the JDK
// so that the CLV framework may invoke them via
// the JDK cert path apis.
if (Security.getProvider(MY_JDK_SECURITY_PROVIDER_NAME) == null) {
   AccessController.doPrivileged(
     new PrivilegedAction() {
       public Object run() {
         Security.addProvider(new MyJDKSecurityProvider());
         return null;
       }
     }
   );
}
:
// This class implements the JDK security provider that registers 
// this provider's cert path builder and cert path validator implementations 
// with the JDK.
private class MyJDKSecurityProvider extends Provider
 {
   private MyJDKSecurityProvider()
    {
      super(MY_JDK_SECURITY_PROVIDER_NAME, 1.0, "MyCertPathProvider JDK CertPath provider");
      put("CertPathBuilder." + BUILDER_ALGORITHM,
 "com.acme.MyPathProviderRuntimeImpl$MyJDKCertPathBuilder");
      put("CertPathValidator." + VALIDATOR_ALGORITHM,
 "com.acme.MyCertPathProviderRuntimeImpl$MyJDKCertPathValidator");
    }
 }
}

Use the CertPathBuilderParametersSpi SSPI in Your CertPathBuilderSpi Implementation

Your JDK implementation will be passed a JDK CertPathParameters object that you can cast to a WebLogic CertPathBuilderParametersSpi. You can then access its WebLogic methods to get the trusted CA's, selector, and ContextHandler. You can also use it to access your WebLogic CertPath provider object. The following methods are provided:

  • getCertPathProvider

    CertPathProvider getCertPathProvider() 
    

    Gets the CertPath Provider SSPI interface that exposes the services provided by a CertPath provider to the WebLogic Security Framework. In particular, you use the initialize method of the CertPath provider SSPI to hook into the MBean and make its custom configuration data available to your CertPathBuilderSpi implementation, as shown in Example 15-2.

  • getCertPathSelector

    CertPathSelector getCertPathSelector() 
    

    Gets the CertPathSelector interface that holds the selection criteria for finding the CertPath.

    WebLogic Server provides a set of classes in weblogic.security.pk that implement the CertPathSelector interface, one for each supported type of certificate chain lookup. Therefore, the getCertPathSelector method returns one of the following derived classes:

  • EndCertificateSelector – used to find and validate a certificate chain given its end certificate.

  • IssuerDNSerialNumberSelector – used to find and validate a certificate chain from its end certificate's issuer DN and serial number.

  • SubjectDNSelector – used to find and validate a certificate chain from its end certificate's subject DN.

  • SubjectKeyIdentifierSelector – used to find and validate a certificate chain from its end certificate's subject key identifier (an optional field in X509 certificates).

    Each selector class has one or more methods to retrieve the selection data and a constructor.

    Your CertPathBuilderSpi implementation decides which selectors it supports. The CertPathBuilderSpi implementation must use the getCertPathSelector method of the CertPathBuilderParametersSpi SSPI to get the CertPathSelector that holds the selection criteria for finding the CertPath. If your CertPathBuilderSpi implementation supports that type of selector, it then uses the selector to build and validate the chain. Otherwise, it must throw an InvalidAlgorithmParameterException, which is propagated back to the caller.

  • getContext()

    ContextHandler getContext() 
    

    Gets a ContextHandler that may pass in extra parameters that can be used for building and validating the CertPath.

  • getTrustedCAs()

    X509Certificate[] getTrustedCAs() 
    

    Gets a list of trusted certificate authorities that may be used for building the certificate chain. If your CertPathBuilderSpi implementation needs Trusted CA's to build the chain, it should use these Trusted CA's.

  • clone

    Object clone()
    

    This interface is not cloneable.

Use the CertPathValidatorParametersSpi SSPI in Your CertPathValidatorSpi Implementation

Your JDK implementation will be passed a JDK CertPathParameters object that you can cast to a WebLogic CertPathValidatorParametersSpi. You can then access its WebLogic methods to get the trusted CA's and ContextHandler. You can also use it to access your WebLogic CertPath provider object. The CLV framework ensures that the certificate chain passed to the validator SPI is in order (starting at the end certificate), and that each cert has signed the next. The following methods are provided:

  • getCertPathProvider

    CertPathProvider getCertPathProvider() 
    

    Gets the CertPath Provider SSPI interface that exposes the services provided by a CertPath provider to the WebLogic Security Framework. In particular, you use the initialize method of the CertPath provider SSPI to hook into the MBean and make its custom configuration data available to your CertPathValidatorSpi implementation, as shown in Example 15-2.

  • getContext()

    ContextHandler getContext() 
    

    Gets a ContextHandler that may pass in extra parameters that can be used for building and validating the CertPath.

    SSL performs some built-in validation before it calls one or more CertPathValidator objects to perform additional validation. A validator can reduce the amount of validation it must do by discovering what validation has already been done.

    For example, the WebLogic CertPath Provider performs the same Certicom validation that SSL does, and there is no need to duplicate that validation when invoked by SSL. Therefore, SSL puts some information into the context it hands to the validators to indicate what validation has already occurred. The weblogic.security.SSL.SSLValidationConstants CHAIN_PREVALIDATED_BY_SSL field is a Boolean that indicates whether SSL has pre-validated the certificate chain. Your application code can test this field, which is set to true if SSL has pre-validated the certificate chain, and is false otherwise.

  • getTrustedCAs()

    X509Certificate[] getTrustedCAs() 
    

    Gets a list of trusted certificate authorities that may be used for validating the certificate chain. If your CertPathBuilderSpi implementation needs Trusted CA's to validate the chain, it should use these Trusted CA's.

  • clone

    Object clone() 
    

    This interface is not cloneable.

Returning the Builder or Validator Results

Your JDK CertPathBuilder or CertPathValidator implementation must return an object that implements the java.security.cert.CertPathValidatorResult or java.security.cert.CertPathValidatorResult interface.

You can write your own results implementation or you can use the WebLogic Server convenience routines.

WebLogic Server provides two convenience results-implementation classes, WLSCertPathBuilderResult and WLSCertPathValidatorResult, both of which are located in weblogic.security.pk, that you can use to return instances of java.security.cert.CertPathValidatorResult or java.security.cert.CertPathValidatorResult.

Note:

The results you return are not passed through the WebLogic Security framework.

Example: Creating the Sample Cert Path Provider

Example 15-6 shows an example CertPath builder/validator provider. The example includes extensive comments that explain the code flow.

Example 15-1 shows the CertPath MBean that Example 15-6 uses.

Example 15-6 Creating the Sample Cert Path Provider

package com.acme;

import weblogic.management.security.ProviderMBean;
import weblogic.security.pk.CertPathSelector;
import weblogic.security.pk.SubjectDNSelector;
import weblogic.security.pk.WLSCertPathBuilderResult;
import weblogic.security.pk.WLSCertPathValidatorResult;
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.CertPathBuilderParametersSpi;
import weblogic.security.spi.CertPathProvider;
import weblogic.security.spi.CertPathValidatorParametersSpi;
import weblogic.security.spi.SecurityServices;
import weblogic.security.SSL.SSLValidationConstants;

import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.security.cert.CertPath;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderResult;
import java.security.cert.CertPathBuilderSpi;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertPathParameters;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.CertPathValidatorSpi;
import java.security.cert.CertPathValidatorException;
import java.security.cert.X509Certificate;

public class MyCertPathProviderRuntimeImpl implements CertPathProvider
{
   private static final String MY_JDK_SECURITY_PROVIDER_NAME = "MyCertPathProvider";
   private static final String BUILDER_ALGORITHM = MY_JDK_SECURITY_PROVIDER_NAME + "CertPathBuilder";
   private static final String VALIDATOR_ALGORITHM = MY_JDK_SECURITY_PROVIDER_NAME + "CertPathValidator";

   // Used to invoke my JDK cert path builder / validator implementations
   private CertPathBuilder   certPathBuilder;
   private CertPathValidator certPathValidator;

   // remember my custom configuration data from my mbean
   private String customConfigData;

   private String description;

   public void initialize(ProviderMBean mBean, SecurityServices securityServices)
   {
     MyCertPathProviderMBean myMBean = (MyCertPathProviderMBean)mBean;

     description = myMBean.getDescription();

     customConfigData = myMBean.getCustomConfigData();

     // register my cert path impls with the JDK
     // so that the CLV framework may invoke them via
     // the JDK cert path apis.
     if (Security.getProvider(MY_JDK_SECURITY_PROVIDER_NAME) == null) {
       AccessController.doPrivileged(
         new PrivilegedAction() {
           public Object run() {
            Security.addProvider(new MyJDKSecurityProvider());
             return null;
           }
         }
       );
     }

     // get my JDK cert path impls
     try {
       certPathBuilder = CertPathBuilder.getInstance(BUILDER_ALGORITHM);
     } catch (NoSuchAlgorithmException e) { throw new AssertionError("..."); }

     try {
       certPathValidator = CertPathValidator.getInstance(VALIDATOR_ALGORITHM);
     } catch (NoSuchAlgorithmException e) { throw new AssertionError("..."); }
   }

   public void             shutdown          () {                     }
   public String           getDescription       () { return description;    }
   public CertPathBuilder  getCertPathBuilder   () { return certPathBuilder;}
   public CertPathValidator getCertPathValidator () { return certPathValidator;}

   // make my config data available to my JDK CertPathBuilderSpi and    
   // CertPathValidatorSpi impls
   private String getCustomConfigData() { return customConfigData; }

   /**
   * This class contains JDK cert path builder implementation for this provider.
   */

   static public class MyJDKCertPathBuilder extends CertPathBuilderSpi
    {
     public CertPathBuilderResult
      engineBuild(CertPathParameters genericParams)
       throws CertPathBuilderException, InvalidAlgorithmParameterException
     {

   // narrow the CertPathParameters to the WLS ones so we can get the
   // data needed to build and validate the cert path
   if (!(genericParams instanceof CertPathBuilderParametersSpi)) {
     throw new InvalidAlgorithmParameterException("The CertPathParameters must be a
 weblogic.security.pk.CertPathBuilderParametersSpi instance.");
   }

   CertPathBuilderParametersSpi params = (CertPathBuilderParametersSpi)genericParams;

   // get my runtime implementation instance which holds the configuration
   // data needed to build and validate the cert path
   MyCertPathProviderRuntimeImpl runtime = (MyCertPathProviderRuntimeImpl)params.getCertPathProvider();
   String myCustomConfigData = runtime.getCustomConfigData();

   // get the selector which indicates which cert path the caller wants built.
   // it can be an EndCertificateSelector, SubjectDNSelector,    
   // IssuerDNSerialNumberSelector
   // or a SubjectKeyIdentifier.
   CertPathSelector genericSelector = params.getCertPathSelector();

   // decide which kinds of selectors this builder wants to support.

   if (genericSelector instanceof SubjectDNSelector) {

    // get the subject dn of the end certificate of the cert path the caller     
   // wants built
    SubjectDNSelector selector = (SubjectDNSelector)genericSelector;
    String subjectDN = selector.getSubjectDN();

   // if your implementation requires trusted CAs, get them.
   // otherwise, ignore them.  that is, it's a quality of service
   // issue whether or not you require trusted CAs.
   X509Certificate[] trustedCAs = params.getTrustedCAs();

   // if your implementation requires looks for extra data in
   // the context handler, get it.  otherwise ignore it.
   ContextHandler context = params.getContext();
   if (context != null) {
   // ...
   }

   // use my custom configuration data (ie. myCustomConfigData),
   // the trusted CAs (if applicable to my implementation),
   // the context (if applicable to my implementation),
   // and the subject DN to build and validate the cert path
   CertPath certpath = ...
   // or X509Certificate[] chain = ...

   // if not found, throw an exception:
   if (...) {
    throw new CertPathBuilderException("Could not build a cert path for " + subjectDN);
   }

   // if not valid, throw an exception:
   if (...) { 
    throw new CertPathBuilderException("Could not validate the cert path for " + subjectDN);
   }

   // if found and valid, return the cert path.
   // for convenience, use the WLSCertPathBuilderResult class
   return new WLSCertPathBuilderResult(certpath);
   // or return new WLSCertPathBuilderResult(chain);

   } else {

   // the caller passed in a selector that my implementation does not support
   throw new InvalidAlgorithmParameterException("MyCertPathProvider only
   supports weblogoic.security.pk.SubjectDNSelector");
   }
  }
}

   /**
   * This class contains JDK cert path validator implementation for this provider.
   */

   static public class MyJDKCertPathValidator extends CertPathValidatorSpi
   {
     public CertPathValidatorResult
      engineValidate(CertPath certPath, CertPathParameters genericParams)
       throws CertPathValidatorException, InvalidAlgorithmParameterException
     {

   // narrow the CertPathParameters to the WLS ones so we can get the
   // data needed to build and validate the cert path
   if (!(genericParams instanceof CertPathValidatorParametersSpi)) {
     throw new InvalidAlgorithmParameterException("The CertPathParameters must be a
 weblogic.security.pk.CertPathValidatorParametersSpi instance.");
   }

     CertPathValidatorParametersSpi params = (CertPathValidatorParametersSpi)genericParams;


     // get my runtime implementation instance which holds the configuration
     // data needed to build and validate the cert path
     MyCertPathProviderRuntimeImpl runtime = (MyCertPathProviderRuntimeImpl)params.getCertPathProvider();
     String myCustomConfigData = runtime.getCustomConfigData();

     // if your implementation requires trusted CAs, get them.
     // otherwise, ignore them.  that is, it's a quality of service
     // issue whether or not you require trusted CAs.
     X509Certificate[] trustedCAs = params.getTrustedCAs();

     // if your implementation requires looks for extra data in
     // the context handler, get it.  otherwise ignore it.
     ContextHandler context = params.getContext();
     if (context != null) {
       // ...
     }

     // The CLV framework has already done some minimal validation
     // on the cert path before sending it to your provider:
     //   1) the cert path is not empty
     //   2) the cert path starts with the end cert
     //   3) each certificate in the cert path was issued and
     //      signed by the next certificate in the chain
     //      So, your validator can rely on these checks having
     //      already been performed (vs your validator needing to
     //      do these checks too).

   // Use my custom configuration data (ie. myCustomConfigData),
   // the trusted CAs (if applicable to my implementation),
   // and the context (if applicable to my implementation)
   // to validate the cert path

   // if not valid, throw an exception:
   if (...) {
     throw new CertPathValidatorException("Could not validate the cerpath " + certPath);
   }
   // if valid, return success

   // For convenience, use the WLSCertPathValidatorResult class

   return new WLSCertPathValidatorResult();
  }
}

   // This class implements the JDK security provider that registers this    // provider's
   // cert path builder and cert path validator implementations with the JDK.
   private class MyJDKSecurityProvider extends Provider
   {
   private MyJDKSecurityProvider()
   {
     super(MY_JDK_SECURITY_PROVIDER_NAME, 1.0, "MyCertPathProvider JDK CertPath provider");
     put("CertPathBuilder." + BUILDER_ALGORITHM, "com.acme.MyPathProviderRuntimeImpl$MyJDKCertPathBuilder");
     put("CertPathValidator." + VALIDATOR_ALGORITHM, "com.acme.MyCertPathProviderRuntimeImpl$MyJDKCertPathValidator");
   }
  }
}

Generate an MBean Type Using the WebLogic MBeanMaker

Before you start generating an MBean type for your custom security provider, you should first:

When you understand this information and have made your design decisions, create the MBean type for your custom CertPath provider by following these steps:

Create an MBean Definition File (MDF)

Use the WebLogic MBeanMaker to Generate the MBean Type

Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF)

Install the MBean Type Into the WebLogic Server Environment

Note:

Several sample security providers (available at https://codesamples.samplecode.oracle.com/servlets/tracking?id=S224 on the Oracle Technology Network Web site) illustrate how to perform these steps.

All instructions provided in this section assume that you are working in a Windows environment.

Create an MBean Definition File (MDF)

To create an MBean Definition File (MDF), follow these steps:

  1. Copy the MDF for the sample Authentication provider to a text file.

    Note:

    MDF for the sample Authentication provider is called SimpleSampleAuthenticator.xml. There is no sample CertPath provider.
  2. Modify the content of the <MBeanType> and <MBeanAttribute> elements in your MDF so that they are appropriate for your custom CertPath provider. You need to extend or implement CertPathBuilderMBean or CertPathValidatorMBean.

  3. Add any custom attributes and operations (that is, additional <MBeanAttribute> and <MBeanOperation> elements) to your MDF.

  4. Save the file.

    Note:

    A complete reference of MDF element syntax is available in Appendix A, "MBean Definition File (MDF) Element Syntax."

Use the WebLogic MBeanMaker to Generate the MBean Type

Once you create your MDF, you are ready to run it through the WebLogic MBeanMaker. The WebLogic MBeanMaker is currently a command-line utility that takes as its input an MDF, and outputs some intermediate Java files, including an MBean interface, an MBean implementation, and an associated MBean information file. Together, these intermediate files form the MBean type for your custom security provider.

The instructions for generating an MBean type differ based on the design of your custom CertPath provider. Follow the instructions that are appropriate to your situation:

No Optional SSPI MBeans and No Custom Operations

If the MDF for your custom CertPath provider does not implement any optional SSPI MBeans and does not include any custom operations, follow these steps:

  1. Create a new DOS shell.

  2. Type the following command:

    java -DMDF=xmlfile -Dfiles=filesdir -DcreateStubs=true weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMDF flag indicates that the WebLogic MBeanMaker should translate the MDF into code, xmlFile is the MDF (the XML MBean Description File) and filesdir is the location where the WebLogic MBeanMaker will place the intermediate files for the MBean type.

    Whenever xmlfile is provided, a new set of output files is generated.

    Each time you use the -DcreateStubs=true flag, it overwrites any existing MBean implementation file.

    Note:

    As of version 9.0 of WebLogic Server, you can also provide a directory that contains multiple MDF's by using the -DMDFDIR <MDF directory name> option. In prior versions of WebLogic Server, the WebLogic MBeanMaker processed only one MDF at a time. Therefore, you had to repeat this process if you had multiple MDFs (in other words, multiple CertPath providers).
  3. Proceed to Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF).

Optional SSPI MBeans or Custom Operations

If the MDF for your custom CertPath provider does implement some optional SSPI MBeans or does include custom operations, consider the following:

Are you creating an MBean type for the first time? If so, follow these steps:

  1. Create a new DOS shell.

  2. Type the following command:

    java -DMDF=xmlfile -Dfiles=filesdir -DcreateStubs=true weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMDF flag indicates that the WebLogic MBeanMaker should translate the MDF into code, xmlFile is the MDF (the XML MBean Description File) and filesdir is the location where the WebLogic MBeanMaker will place the intermediate files for the MBean type.

    Whenever xmlfile is provided, a new set of output files is generated.

    Each time you use the -DcreateStubs=true flag, it overwrites any existing MBean implementation file.

    Note:

    As of version 9.0 of WebLogic Server, you can also provide a directory that contains multiple MDF's by using the -DMDFDIR <MDF directory name> option. In prior versions of WebLogic Server, the WebLogic MBeanMaker processed only one MDF at a time. Therefore, you had to repeat this process if you had multiple MDFs (in other words, multiple CertPath providers).
  3. If you implemented optional SSPI MBeans in your MDF, follow these steps:

    1. Locate the MBean implementation file.

      The MBean implementation file generated by the WebLogic MBeanMaker is named MBeanNameImpl.java. For example, for the MDF named SampleIdentityAsserter, the MBean implementation file to be edited is named SampleIdentityAsserterImpl.java.

    2. For each optional SSPI MBean that you implemented in your MDF, implement each method. Be sure to also provide implementations for any methods that the optional SSPI MBean inherits.

  4. If you included any custom operations in your MDF, implement the methods using the method stubs.

  5. Save the file.

  6. Proceed to Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF).

Are you updating an existing MBean type? If so, follow these steps:

  1. Copy your existing MBean implementation file to a temporary directory so that your current method implementations are not overwritten by the WebLogic MBeanMaker.

  2. Create a new DOS shell.

  3. Type the following command:

    java -DMDF=xmlfile -Dfiles=filesdir -DcreateStubs=true weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMDF flag indicates that the WebLogic MBeanMaker should translate the MDF into code, xmlFile is the MDF (the XML MBean Description File) and filesdir is the location where the WebLogic MBeanMaker will place the intermediate files for the MBean type.

    Whenever xmlfile is provided, a new set of output files is generated.

    Each time you use the -DcreateStubs=true flag, it overwrites any existing MBean implementation file.

    Note:

    As of version 9.0 of WebLogic Server, you can also provide a directory that contains multiple MDF's by using the -DMDFDIR <MDF directory name> option. In prior versions of WebLogic Server, the WebLogic MBeanMaker processed only one MDF at a time. Therefore, you had to repeat this process if you had multiple MDFs (in other words, multiple Cert Path providers).
  4. If you implemented optional SSPI MBeans in your MDF, follow these steps:

    1. Locate and open the MBean implementation file.

      The MBean implementation file generated by the WebLogic MBeanMaker is named MBeanNameImpl.java. For example, for the MDF named SampleIdentityAsserter, the MBean implementation file to be edited is named SampleIdentityAsserterImpl.java.

    2. Open your existing MBean implementation file (which you saved to a temporary directory in step 1).

    3. Synchronize the existing MBean implementation file with the MBean implementation file generated by the WebLogic MBeanMaker.

      Accomplishing this task may include, but is not limited to: copying the method implementations from your existing MBean implementation file into the newly-generated MBean implementation file (or, alternatively, adding the new methods from the newly-generated MBean implementation file to your existing MBean implementation file), and verifying that any changes to method signatures are reflected in the version of the MBean implementation file that you are going to use (for methods that exist in both MBean implementation files).

    4. If you modified the MDF to implement optional SSPI MBeans that were not in the original MDF, implement each method. Be sure to also provide implementations for any methods that the optional SSPI MBean inherits.

  5. If you modified the MDF to include any custom operations that were not in the original MDF, implement the methods using the method stubs.

  6. Save the version of the MBean implementation file that is complete (that is, has all methods implemented).

  7. Copy this MBean implementation file into the directory where the WebLogic MBeanMaker placed the intermediate files for the MBean type. You specified this as filesdir in step 3. (You will be overriding the MBean implementation file generated by the WebLogic MBeanMaker as a result of step 3.)

  8. Proceed to Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF).

About the Generated MBean Interface File

The MBean interface file is the client-side API to the MBean that your runtime class or your MBean implementation will use to obtain configuration data. It is typically used in the initialize method as described in Understand the Purpose of the "Provider" SSPIs.

Because the WebLogic MBeanMaker generates MBean types from the MDF you created, the generated MBean interface file will have the name of the MDF, plus the text "MBean" appended to it. For example, the result of running the SampleIdentityAsserter MDF through the WebLogic MBeanMaker will yield an MBean interface file called SampleIdentityAsserterMBean.java.

Use the WebLogic MBeanMaker to Create the MBean JAR File (MJF)

Once your have run your MDF through the WebLogic MBeanMaker to generate your intermediate files, and you have edited the MBean implementation file to supply implementations for the appropriate methods within it, you need to package the MBean files and the runtime classes for the custom CertPath provider into an MBean JAR File (MJF). The WebLogic MBeanMaker also automates this process.

To create an MJF for your custom CertPath provider, follow these steps:

  1. Create a new DOS shell.

  2. Type the following command:

    java -DMJF=jarfile -Dfiles=filesdir weblogic.management.commo.WebLogicMBeanMaker
    

    where the -DMJF flag indicates that the WebLogic MBeanMaker should build a JAR file containing the new MBean types, jarfile is the name for the MJF and filesdir is the location where the WebLogic MBeanMaker looks for the files to JAR into the MJF.

    Compilation occurs at this point, so errors are possible. If jarfile is provided, and no errors occur, an MJF is created with the specified name.

    Note:

    When you create a JAR file for a custom security provider, a set of XML binding classes and a schema are also generated. You can choose a namespace to associate with that schema. Doing so avoids the possibility that your custom classes will conflict with those provided by Oracle. The default for the namespace is vendor. You can change this default by passing the -targetNameSpace argument to the WebLogicMBeanMaker or the associated WLMBeanMaker ant task.

    If you want to update an existing MJF, simply delete the MJF and regenerate it. The WebLogic MBeanMaker also has a -DIncludeSource option, which controls whether source files are included into the resulting MJF. Source files include both the generated source and the MDF itself. The default is false. This option is ignored when -DMJF is not used.

The resulting MJF can be installed into your WebLogic Server environment, or distributed to your customers for installation into their WebLogic Server environments.

Install the MBean Type Into the WebLogic Server Environment

To install an MBean type into the WebLogic Server environment, copy the MJF into the WL_HOME\server\lib\mbeantypes directory, where WL_HOME is the top-level installation directory for WebLogic Server. This "deploys" your custom CertPath provider—that is, it makes the custom CertPath provider manageable from the WebLogic Server Administration Console.

Note:

WL_HOME\server\lib\mbeantypes is the default directory for installing MBean types. (Beginning with 9.0, security providers can be loaded from ...\domaindir\lib\mbeantypes as well.) However, if you want WebLogic Server to look for MBean types in additional directories, use the -Dweblogic.alternateTypesDirectory=<dir> command-line flag when starting your server, where <dir> is a comma-separated list of directory names. When you use this flag, WebLogic Server will always load MBean types from WL_HOME\server\lib\mbeantypes first, then will look in the additional directories and load all valid archives present in those directories (regardless of their extension).

For example, if -Dweblogic.alternateTypesDirectory = dirX,dirY, WebLogic Server will first load MBean types from WL_HOME\server\lib\mbeantypes, then any valid archives present in dirX and dirY. If you instruct WebLogic Server to look in additional directories for MBean types and are using the Java Security Manager, you must also update the weblogic.policy file to grant appropriate permissions for the MBean type (and thus, the custom security provider). For more information, see "Using Java Security to Protect WebLogic Resources" in Programming Security for Oracle WebLogic Server.

You can create instances of the MBean type by configuring your custom CertPath provider (see Configure the Custom CertPath Provider Using the Administration Console), and then use those MBean instances from a GUI, from other Java code, or from APIs. For example, you can use the WebLogic Server Administration Console to get and set attributes and invoke operations, or you can develop other Java objects that instantiate MBeans and automatically respond to information that the MBeans supply. We recommend that you back up these MBean instances.

Configure the Custom CertPath Provider Using the Administration Console

Configuring a custom CertPath provider means that you are adding the custom CertPath provider to your security realm, where it can be accessed by applications requiring CertPath services.

Configuring custom security providers is an administrative task, but it is a task that may also be performed by developers of custom security providers.

Note:

The steps for configuring a custom CertPath provider using the WebLogic Server Administration Console are described under "Configuring WebLogic Security Providers" in Securing Oracle WebLogic Server.