[Pki-devel] [PATCH] 0026 Add lightweight sub-CA support

Fraser Tweedale ftweedal at redhat.com
Fri Mar 6 08:16:29 UTC 2015


G'day,

The first major patch for lightweight sub-CAs is attached for
review.  Some important features are not yet implemented in this
patch:

- Sub-CA creation

- Caching of sub-CA instances

- Signing key replication for clones

- CRLs (the OCSP servlet works for sub-CAs, however)

- Sub-CA support is possibly missing from some web servlets /
  templates.  Let me know if you hit any.


Because sub-CA creation is not implemented, if you want to test this
patch you will need to:

1. Use the top-level CA to sign a sub-CA certificate and manually
  install it in the NSSDB with the nickname:
      "${TOPLEVEL_CA_NICKNAME} ${SUB_CA_HANDLE}"

2. Create the sub-CA certificate repository OU:
      "ou=${SUB_CA_HANDLE},ou=certificateRepository,ou=ca,o=pki-tomcat-CA"

3. When submitting requests or other queries via HTTP, edit the
  initial link target or form action to include the query parameter:
      "?caRef=${SUB_CA_HANDLE}"
  (Subsequent pages should not require this intervention.)


I have also updated the design proposal with some refinements and
details of the implementation so far:
http://pki.fedoraproject.org/wiki/Lightweight_sub-CAs

Looking forward to your feedback / bug reports!
Fraser
-------------- next part --------------
>From 711a0601073068ce89e76ce7093d3665a5022ccc Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <frase at frase.id.au>
Date: Wed, 28 Jan 2015 02:41:10 -0500
Subject: [PATCH] Add lightweight sub-CA support

---
 .../shared/webapps/ca/agent/ca/queryCert.template  |  9 ++-
 .../webapps/ca/agent/ca/reasonToRevoke.template    |  2 +
 .../shared/webapps/ca/agent/ca/srchCert.template   |  2 +
 base/ca/shared/webapps/ca/ee/ca/queryCert.template |  6 +-
 .../webapps/ca/ee/ca/reasonToRevoke.template       |  2 +
 .../src/com/netscape/ca/CertificateAuthority.java  | 90 ++++++++++++++++++++--
 base/ca/src/com/netscape/ca/SigningUnit.java       | 10 ++-
 .../netscape/certsrv/ca/ICertificateAuthority.java | 17 ++++
 .../netscape/certsrv/profile/IEnrollProfile.java   |  5 ++
 .../cms/profile/common/CAEnrollProfile.java        |  7 +-
 .../netscape/cms/profile/common/EnrollProfile.java |  3 +
 .../cms/profile/def/AuthInfoAccessExtDefault.java  |  8 +-
 .../def/AuthorityKeyIdentifierExtDefault.java      | 17 +++-
 .../netscape/cms/profile/def/CAEnrollDefault.java  |  4 +-
 .../netscape/cms/servlet/cert/DisplayBySerial.java | 31 ++++----
 .../com/netscape/cms/servlet/cert/DoRevoke.java    | 15 ++--
 .../cms/servlet/cert/EnrollmentProcessor.java      |  7 ++
 .../com/netscape/cms/servlet/cert/ListCerts.java   | 23 +++---
 .../netscape/cms/servlet/cert/ReasonToRevoke.java  | 13 ++--
 .../com/netscape/cms/servlet/cert/SrchCerts.java   | 24 +++---
 .../com/netscape/cms/servlet/ocsp/OCSPServlet.java |  5 +-
 21 files changed, 227 insertions(+), 73 deletions(-)

diff --git a/base/ca/shared/webapps/ca/agent/ca/queryCert.template b/base/ca/shared/webapps/ca/agent/ca/queryCert.template
index 40ee64b0c0b62a0ff409f2617b956647b8779b59..39f933bcd9cd777a22e1baf4fdc4d8e33e5295bc 100644
--- a/base/ca/shared/webapps/ca/agent/ca/queryCert.template
+++ b/base/ca/shared/webapps/ca/agent/ca/queryCert.template
@@ -321,8 +321,10 @@ function displayCertificateRecord(i, cert)
      "<td style='overflow: hidden; white-space: nowrap;'>"+
      "     <font face='PrimaSans BT, Verdana, sans-serif' size='-1'>\n"+
      "   <div style='overflow: hidden; white-space: nowrap;'>"+
-     " <a index='"+i+"' href='displayBySerial?op=displayBySerial&serialNumber=0x"+
-           cert.serialNumber+"' onmouseover='mouseover(this,event);' "+
+     " <a index='"+i+"' href='displayBySerial?op=displayBySerial"
+        + "&serialNumber=0x" + cert.serialNumber
+        + (result.header.caRef ? "&caRef=" + result.header.caRef : "")
+        + "' onmouseover='mouseover(this,event);' "+
            "onmouseout='mouseout(this);'>"+
          cert.subject+"</a></div></font>"+
      "</td>"+
@@ -419,6 +421,7 @@ function doNext(element)
 	var form = element.form;
 //	form.action = "/"+result.header.op;
         form.action = "/ca/agent/ca/listCerts";
+        form.caRef.value = result.header.caRef || "";
 	form.op.value = result.header.op;
         form.queryCertFilter.value = result.header.queryCertFilter;
         form.direction.value= "down";
@@ -472,6 +475,8 @@ document.write(
 "<button "+disabledUp+" NAME=up onClick='doNext(this)' VALUE='<' width='72'><</button>\n"+
 "<INPUT TYPE=hidden NAME=totalRecordCount VALUE='"+
 result.header.totalRecordCount+ "'>\n"+
+"<INPUT TYPE=hidden NAME=caRef VALUE='"+
+(result.header.caRef || "") + "'>\n"+
 "<INPUT TYPE=hidden NAME=queryCertFilter VALUE='"+
 result.header.queryCertFilter+ "'>\n"+
 "<INPUT TYPE=hidden NAME=querySentinelDown VALUE='"+
diff --git a/base/ca/shared/webapps/ca/agent/ca/reasonToRevoke.template b/base/ca/shared/webapps/ca/agent/ca/reasonToRevoke.template
index ffb648beb117a304a5b6382c129dade20fbb3a09..560bd11d310ad8cc03b441f3edba41174277f02b 100644
--- a/base/ca/shared/webapps/ca/agent/ca/reasonToRevoke.template
+++ b/base/ca/shared/webapps/ca/agent/ca/reasonToRevoke.template
@@ -461,6 +461,8 @@ function revokeCert(serialNumber)
                          result.recordSet[i].serialNumber +"\">");
             }
         }
+        document.writeln("<INPUT TYPE=hidden name=caRef value=\"" +
+                         (result.header.caRef || "") + "\">");
         document.writeln("<INPUT TYPE=hidden name=revokeAll value=\"" +
                          result.header.revokeAll +"\">");
         document.writeln("<INPUT TYPE=hidden name=totalRecordCount value=\"" +
diff --git a/base/ca/shared/webapps/ca/agent/ca/srchCert.template b/base/ca/shared/webapps/ca/agent/ca/srchCert.template
index 001b0e3b5bde043997b6bdb4e1e12f3e10e87526..ebd59822806953ba6500a02b94a1219eba2fe534 100644
--- a/base/ca/shared/webapps/ca/agent/ca/srchCert.template
+++ b/base/ca/shared/webapps/ca/agent/ca/srchCert.template
@@ -106,6 +106,7 @@ function renderDetailsButton(serialNumber)
 	return "<FORM METHOD=post "+
 "ACTION=\""+ "displayBySerial" +"\">\n"+
 "<INPUT TYPE=hidden NAME=\"op\" VALUE=\""+ "displayBySerial" +"\">\n"+
+"<INPUT TYPE=hidden NAME=\"caRef\" VALUE=\"" + (result.header.caRef || "") + "\">\n" +
 "<INPUT TYPE=hidden NAME=\"serialNumber\" VALUE=\""+ "0x"+serialNumber +"\">\n"+
 "<INPUT TYPE=submit VALUE=\"Details\" width=\"72\"></FORM>\n";
 }
@@ -118,6 +119,7 @@ function renderRevokeButton(serialNumberDecimal)
 //"onSubmit=\"return revokeCert("+serialNumberDecimal+");\" "+
 "ACTION=\""+ "reasonToRevoke" +"\">\n"+
 "<INPUT TYPE=hidden NAME=\"op\" VALUE=\""+ "reasonToRevoke" +"\">\n"+
+"<INPUT TYPE=hidden NAME=\"caRef\" VALUE=\"" + (result.header.caRef || "") + "\">\n" +
 "<INPUT TYPE=hidden NAME=\"serialNumber\" VALUE=\""+ serialNumberDecimal +"\">\n"+
 "<INPUT TYPE=hidden NAME=\"revokeAll\" VALUE=\"(&(certRecordId="+serialNumberDecimal+"))\">\n"+
 "<INPUT TYPE=hidden NAME=\"totalRecordCount\" VALUE=\"1\">\n"+
diff --git a/base/ca/shared/webapps/ca/ee/ca/queryCert.template b/base/ca/shared/webapps/ca/ee/ca/queryCert.template
index 1165cb309431cf4e7f83eed6759925b86d11d23e..e8f7541ba26563feec07d15b764aea63ff9789e6 100644
--- a/base/ca/shared/webapps/ca/ee/ca/queryCert.template
+++ b/base/ca/shared/webapps/ca/ee/ca/queryCert.template
@@ -301,8 +301,10 @@ function displayCertificateRecord(i, cert)
      "<td style='overflow: hidden; white-space: nowrap;'>"+
      "     <font face='PrimaSans BT, Verdana, sans-serif' size='-1'>\n"+
      "   <div style='overflow: hidden; white-space: nowrap;'>"+
-     " <a index='"+i+"' href='/ca/ee/ca/displayBySerial?op=displayBySerial&serialNumber=0x"+
-           cert.serialNumber+"' onmouseover='mouseover(this,event);' "+
+     " <a index='"+i+"' href='/ca/ee/ca/displayBySerial?op=displayBySerial"
+        + "&serialNumber=0x" + cert.serialNumber
+        + (result.header.caRef ? "&caRef=" + result.header.caRef : "")
+        + "' onmouseover='mouseover(this,event);' " +
            "onmouseout='mouseout(this);'>"+
          addEscapes(cert.subject)+"</a></div></font>"+
      "</td>"+
diff --git a/base/ca/shared/webapps/ca/ee/ca/reasonToRevoke.template b/base/ca/shared/webapps/ca/ee/ca/reasonToRevoke.template
index 2a608438b1f46b7695a8692ed857ce7de6e07d42..4a6abb830cde161223164e49039b68a4b2b891d3 100644
--- a/base/ca/shared/webapps/ca/ee/ca/reasonToRevoke.template
+++ b/base/ca/shared/webapps/ca/ee/ca/reasonToRevoke.template
@@ -448,6 +448,8 @@ function revokeCert(serialNumber)
         <input type="reset" value="Reset" name="reset" width="72">  
 <SCRIPT LANGUAGE="JavaScript">
 //<!--
+        document.writeln("<INPUT TYPE=hidden name=caRef value=\"" +
+                         (result.header.caRef || "") + "\">");
         document.writeln("<INPUT TYPE=hidden name=serialNumber value=\"" +
                          result.header.serialNumber +"\">");
         document.writeln("<INPUT TYPE=hidden name=revokeAll value=\"" +
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index 65296113e1df07f82070d639ee68588f8e0dbaf7..28dde0b23bb71ebc69c7437851534073392ad13c 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -33,6 +33,7 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
 import java.util.Vector;
 
@@ -123,6 +124,9 @@ import com.netscape.cmsutil.ocsp.SingleResponse;
 import com.netscape.cmsutil.ocsp.TBSRequest;
 import com.netscape.cmsutil.ocsp.UnknownInfo;
 
+import org.apache.commons.lang.StringUtils;
+
+
 /**
  * A class represents a Certificate Authority that is
  * responsible for certificate specific operations.
@@ -136,6 +140,9 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
 
     public final static OBJECT_IDENTIFIER OCSP_NONCE = new OBJECT_IDENTIFIER("1.3.6.1.5.5.7.48.1.2");
 
+    protected List<String> subCAHier;
+    protected String subCAOUs;
+
     protected ISubsystem mOwner = null;
     protected IConfigStore mConfig = null;
     protected ILogger mLogger = CMS.getLogger();
@@ -234,6 +241,27 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
      * Constructs a CA subsystem.
      */
     public CertificateAuthority() {
+        subCAHier = new Vector(0);
+        subCAOUs = joinSubCAOUs(subCAHier);
+    }
+
+    /**
+     * Construct a CA subsystem with given owner subsystem, config and
+     * path in CA hierarchy.
+     *
+     * The primary CA has an empty path.  For Sub-CAs, the
+     * certification path runs left-to-right, i.e., CA at index
+     * N is signed by CA at index (N - 1).
+     */
+    public CertificateAuthority(
+            String subsystemId,
+            ISubsystem owner,
+            IConfigStore config,
+            List<String> path) throws EBaseException {
+        subCAHier = path;
+        subCAOUs = joinSubCAOUs(subCAHier);
+        setId(subsystemId);
+        init(owner, config);
     }
 
     /**
@@ -1226,13 +1254,17 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
                 mIssuerObj = new CertificateIssuerName((X500Name)mSubjectObj.get(CertificateIssuerName.DN_NAME));
             }
 
-            mSigningUnit.init(this, caSigningCfg);
+            String handle = null;
+            if (subCAHier != null && subCAHier.size() > 0)
+                handle = StringUtils.join(subCAHier, ",");
+            mSigningUnit.init(this, caSigningCfg, handle);
             CMS.debug("CA signing unit inited");
 
             // for identrus
             IConfigStore CrlStore = mConfig.getSubStore(PROP_CRL_SIGNING_SUBSTORE);
 
-            if (CrlStore != null && CrlStore.size() > 0) {
+            if (CrlStore != null && CrlStore.size() > 0
+                    && (subCAHier == null || subCAHier.size() == 0)) {
                 mCRLSigningUnit = new SigningUnit();
                 mCRLSigningUnit.init(this, mConfig.getSubStore(PROP_CRL_SIGNING_SUBSTORE));
             } else {
@@ -1302,7 +1334,8 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
 
             IConfigStore OCSPStore = mConfig.getSubStore(PROP_OCSP_SIGNING_SUBSTORE);
 
-            if (OCSPStore != null && OCSPStore.size() > 0) {
+            if (OCSPStore != null && OCSPStore.size() > 0
+                    && (subCAHier == null || subCAHier.size() == 0)) {
                 mOCSPSigningUnit = new SigningUnit();
                 mOCSPSigningUnit.init(this, mConfig.getSubStore(PROP_OCSP_SIGNING_SUBSTORE));
                 CMS.debug("Separate OCSP signing unit inited");
@@ -1448,13 +1481,13 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
         String certReposDN = mConfig.getString(PROP_CERT_REPOS_DN, null);
 
         if (certReposDN == null) {
-            certReposDN = "ou=certificateRepository, ou=" + getId() +
+            certReposDN = subCAOUs + "ou=certificateRepository, ou=" + getId() +
                     ", " + getDBSubsystem().getBaseDN();
         }
         String reposDN = mConfig.getString(PROP_REPOS_DN, null);
 
         if (reposDN == null) {
-            reposDN = "ou=certificateRepository, ou=" + getId() +
+            reposDN = subCAOUs + "ou=certificateRepository, ou=" + getId() +
                     ", " + getDBSubsystem().getBaseDN();
         }
 
@@ -2089,4 +2122,51 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
 
         return new SingleResponse(cid, certStatus, thisUpdate, nextUpdate);
     }
+
+    /**
+     * Get the sub-CA specified by a slash-delimited string.
+     *
+     * Leading and trailing slashes are stripped and multiple
+     * slashes appearing together in the interior are treated
+     * as a single delimiter.
+     */
+    public ICertificateAuthority getSubCA(String pathRaw)
+            throws EBaseException {
+        if (pathRaw == null)
+            return this;
+        pathRaw = StringUtils.strip(pathRaw, "/");
+        String[] pathComponents = StringUtils.split(pathRaw, "/");
+        Vector<String> path = new Vector(pathComponents.length);
+        for (String s : pathComponents)
+            path.add(s);
+        return getSubCA(path);
+    }
+
+    /**
+     * Get the sub-CA specified by the relative hierarchy.
+     */
+    public ICertificateAuthority getSubCA(List<String> relHier)
+            throws EBaseException {
+        if (relHier == null || relHier.size() < 1)
+            return this;
+
+        List<String> newHier = new Vector();
+        if (subCAHier != null)
+            newHier.addAll(0, subCAHier);
+        newHier.add(relHier.get(0));
+
+        CertificateAuthority subCA = new CertificateAuthority(
+                getId(), mOwner, mConfig, newHier);
+        return subCA.getSubCA(relHier.subList(1, relHier.size()));
+    }
+
+    private static String joinSubCAOUs(List<String> handles) {
+        String s = "";
+        if (handles != null) {
+            for (String handle : handles) {
+                s = "ou=" + handle + "," + s;
+            }
+        }
+        return s;
+    }
 }
diff --git a/base/ca/src/com/netscape/ca/SigningUnit.java b/base/ca/src/com/netscape/ca/SigningUnit.java
index 2466fb652a46a3b5faede616cb397d18e592f5a0..e8917017b051ba5277194381cb2eb341909df9ae 100644
--- a/base/ca/src/com/netscape/ca/SigningUnit.java
+++ b/base/ca/src/com/netscape/ca/SigningUnit.java
@@ -133,6 +133,11 @@ public final class SigningUnit implements ISigningUnit {
 
     public void init(ISubsystem owner, IConfigStore config)
             throws EBaseException {
+        init(owner, config, null);
+    }
+
+    public void init(ISubsystem owner, IConfigStore config, String caHandle)
+            throws EBaseException {
         mOwner = owner;
         mConfig = config;
 
@@ -140,7 +145,10 @@ public final class SigningUnit implements ISigningUnit {
         try {
             mManager = CryptoManager.getInstance();
 
-            mNickname = getNickName();
+            if (caHandle == null)
+                mNickname = getNickName();
+            else
+                mNickname = getNickName() + " " + caHandle;
 
             tokenname = config.getString(PROP_TOKEN_NAME);
             if (tokenname.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN) ||
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index f87f15420b3ea6e02e5ce47b5c350e86f67ccc9f..7abd79ac8e2ee223318b14ef8dc6331931b273c8 100644
--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
@@ -18,6 +18,7 @@
 package com.netscape.certsrv.ca;
 
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Map;
 
 import javax.servlet.http.HttpServletRequest;
@@ -515,4 +516,20 @@ public interface ICertificateAuthority extends ISubsystem {
 
     public CertificateIssuerName getIssuerObj();
     public CertificateSubjectName getSubjectObj();
+
+    /**
+     * Get the sub-CA specified by a slash-delimited string.
+     *
+     * Leading and trailing slashes are stripped and multiple
+     * slashes appearing together in the interior are treated
+     * as a single delimiter.
+     */
+    public ICertificateAuthority getSubCA(String pathRaw)
+        throws EBaseException;
+
+    /**
+     * Get the sub-CA specified by the relative heirarchy.
+     */
+    public ICertificateAuthority getSubCA(List<String> relHier)
+        throws EBaseException;
 }
diff --git a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java
index 69a39d7e23232a1a0cc6e2fe98305d452234bb8c..a28ffb3586c88d0a92d976531ee682dfb4997337 100644
--- a/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java
+++ b/base/common/src/com/netscape/certsrv/profile/IEnrollProfile.java
@@ -175,6 +175,11 @@ public interface IEnrollProfile extends IProfile {
     public static final String REQUEST_ALGORITHM_PARAMS = "req_algorithm_params";
 
     /**
+     * Reference to requested certificate authority
+     */
+    public static final String REQUEST_AUTHORITY_REF = "req_authority_ref";
+
+    /**
      * Set Default X509CertInfo in the request.
      *
      * @param request profile-based certificate request.
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java
index d0bfdb8a64ee857a3f5ff544e41de905b4660f55..990c3e6e66ccf6424feb385df8f6900a7c9fe153 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java
@@ -95,8 +95,13 @@ public class CAEnrollProfile extends EnrollProfile {
         CMS.debug("CAEnrollProfile: execute reqId=" +
                 request.getRequestId().toString());
         ICertificateAuthority ca = (ICertificateAuthority) getAuthority();
+        try {
+            ca = ca.getSubCA(request.getExtDataInString(REQUEST_AUTHORITY_REF));
+        } catch (EBaseException e) {
+            throw new EProfileException("Could not reach requested CA");
+        }
+
         ICAService caService = (ICAService) ca.getCAService();
-
         if (caService == null) {
             throw new EProfileException("No CA Service");
         }
diff --git a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
index fc17970b3765fc46c46d0f683ddc16ef9dcbe6fc..3c6344b238967a089491448777e43263d66dff9f 100644
--- a/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
+++ b/base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java
@@ -192,6 +192,9 @@ public abstract class EnrollProfile extends BasicProfile
             if (locale != null) {
                 result[i].setExtData(REQUEST_LOCALE, locale.getLanguage());
             }
+
+            // set requested CA
+            result[i].setExtData(REQUEST_AUTHORITY_REF, ctx.get(REQUEST_AUTHORITY_REF));
         }
         return result;
     }
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java
index 36818a90753b75f958cca4dd4c93f18629b93411..3762ad33974529f329eeda7da2dc18b43a3b4306 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthInfoAccessExtDefault.java
@@ -33,6 +33,7 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.common.NameValuePairs;
 import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.property.Descriptor;
 import com.netscape.certsrv.property.EPropertyException;
@@ -403,12 +404,13 @@ public class AuthInfoAccessExtDefault extends EnrollExtDefault {
      */
     public void populate(IRequest request, X509CertInfo info)
             throws EProfileException {
-        AuthInfoAccessExtension ext = createExtension();
+        String caRef = request.getExtDataInString(IEnrollProfile.REQUEST_AUTHORITY_REF);
+        AuthInfoAccessExtension ext = createExtension(caRef);
 
         addExtension(ext.getExtensionId().toString(), ext, info);
     }
 
-    public AuthInfoAccessExtension createExtension() {
+    public AuthInfoAccessExtension createExtension(String caRef) {
         AuthInfoAccessExtension ext = null;
         int num = getNumAds();
 
@@ -433,6 +435,8 @@ public class AuthInfoAccessExtDefault extends EnrollExtDefault {
                             if (hostname != null && port != null)
                                 // location = "http://"+hostname+":"+port+"/ocsp/ee/ocsp";
                                 location = "http://" + hostname + ":" + port + "/ca/ocsp";
+                                if (caRef != null && !caRef.isEmpty())
+                                    location += "?caRef=" + caRef;
                         }
                     }
 
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
index 77fd0a5fdaea2de826ee848fd88883910d4c3f3b..e9a808524434b7990efdf19b1d2df3435152a087 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java
@@ -26,8 +26,11 @@ import netscape.security.x509.PKIXExtensions;
 import netscape.security.x509.X509CertInfo;
 
 import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.profile.EProfileException;
+import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.property.Descriptor;
 import com.netscape.certsrv.property.EPropertyException;
@@ -161,18 +164,26 @@ public class AuthorityKeyIdentifierExtDefault extends CAEnrollDefault {
      */
     public void populate(IRequest request, X509CertInfo info)
             throws EProfileException {
-        AuthorityKeyIdentifierExtension ext = createExtension(info);
+        ICertificateAuthority ca = (ICertificateAuthority)
+                CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+        try {
+            ca = ca.getSubCA(request.getExtDataInString(IEnrollProfile.REQUEST_AUTHORITY_REF));
+        } catch (EBaseException e) {
+            throw new EProfileException("Could not reach requested CA");
+        }
 
+        AuthorityKeyIdentifierExtension ext = createExtension(ca, info);
         addExtension(PKIXExtensions.AuthorityKey_Id.toString(), ext, info);
     }
 
-    public AuthorityKeyIdentifierExtension createExtension(X509CertInfo info) {
+    public AuthorityKeyIdentifierExtension createExtension(
+            ICertificateAuthority ca, X509CertInfo info) {
         KeyIdentifier kid = null;
         String localKey = getConfig("localKey");
         if (localKey != null && localKey.equals("true")) {
             kid = getKeyIdentifier(info);
         } else {
-            kid = getCAKeyIdentifier();
+            kid = getCAKeyIdentifier(ca);
         }
 
         if (kid == null)
diff --git a/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java b/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java
index 1d1d05ed55ef30114781521ac607eae118546250..696830ead842767892f77bd8f8c9ea6f667225aa 100644
--- a/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java
+++ b/base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java
@@ -68,9 +68,7 @@ public abstract class CAEnrollDefault extends EnrollDefault {
         return null;
     }
 
-    public KeyIdentifier getCAKeyIdentifier() {
-        ICertificateAuthority ca = (ICertificateAuthority)
-                CMS.getSubsystem(CMS.SUBSYSTEM_CA);
+    public KeyIdentifier getCAKeyIdentifier(ICertificateAuthority ca) {
         X509CertImpl caCert = ca.getCACert();
         if (caCert == null) {
             // during configuration, we dont have the CA certificate
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java
index 283cf499e1ca6f12da93db40c2cb08cbeba5ad0b..52c0b34def086677e767ce44be8e5a3d2cad4995 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DisplayBySerial.java
@@ -85,7 +85,6 @@ public class DisplayBySerial extends CMSServlet {
     private final static String TPL_FILE1 = "displayBySerial.template";
     private final static BigInteger MINUS_ONE = new BigInteger("-1");
 
-    private ICertificateRepository mCertDB = null;
     private String mForm1Path = null;
     private X509Certificate mCACerts[] = null;
 
@@ -103,9 +102,6 @@ public class DisplayBySerial extends CMSServlet {
      */
     public void init(ServletConfig sc) throws ServletException {
         super.init(sc);
-        if (mAuthority instanceof ICertificateAuthority) {
-            mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
-        }
         try {
             mCACerts = ((ICertAuthority) mAuthority).getCACertChain().getChain();
         } catch (Exception e) {
@@ -143,6 +139,9 @@ public class DisplayBySerial extends CMSServlet {
         CMSTemplate form = null;
         Locale[] locale = new Locale[1];
 
+        ICertificateAuthority targetCA = certAuthority.getSubCA(req.getParameter("caRef"));
+        ICertificateRepository certDB = targetCA.getCertificateRepository();
+
         try {
             AuthzToken authzToken = null;
 
@@ -160,7 +159,7 @@ public class DisplayBySerial extends CMSServlet {
             }
 
             serialNumber = getSerialNumber(req);
-            getCertRecord(serialNumber, certType); //throw exception on error
+            getCertRecord(certDB, serialNumber, certType); //throw exception on error
 
             if (certType[0].equalsIgnoreCase("x509")) {
                 form = getTemplate(mForm1Path, req, locale);
@@ -185,7 +184,7 @@ public class DisplayBySerial extends CMSServlet {
 
         try {
             if (serialNumber.compareTo(MINUS_ONE) > 0) {
-                process(argSet, header, serialNumber,
+                process(certDB, argSet, header, serialNumber,
                         req, resp, locale[0]);
             } else {
                 error = new ECMSGWException(
@@ -222,7 +221,9 @@ public class DisplayBySerial extends CMSServlet {
     /**
      * Display information about a particular certificate
      */
-    private void process(CMSTemplateParams argSet, IArgBlock header,
+    private void process(
+            ICertificateRepository certDB,
+            CMSTemplateParams argSet, IArgBlock header,
             BigInteger seq, HttpServletRequest req,
             HttpServletResponse resp,
             Locale locale)
@@ -230,10 +231,10 @@ public class DisplayBySerial extends CMSServlet {
         String certType[] = new String[1];
 
         try {
-            getCertRecord(seq, certType); // throw exception on error
+            getCertRecord(certDB, seq, certType); // throw exception on error
 
             if (certType[0].equalsIgnoreCase("x509")) {
-                processX509(argSet, header, seq, req, resp, locale);
+                processX509(certDB, argSet, header, seq, req, resp, locale);
                 return;
             }
         } catch (EBaseException e) {
@@ -245,7 +246,9 @@ public class DisplayBySerial extends CMSServlet {
         return;
     }
 
-    private void processX509(CMSTemplateParams argSet, IArgBlock header,
+    private void processX509(
+            ICertificateRepository certDB,
+            CMSTemplateParams argSet, IArgBlock header,
             BigInteger seq, HttpServletRequest req,
             HttpServletResponse resp,
             Locale locale)
@@ -257,7 +260,7 @@ public class DisplayBySerial extends CMSServlet {
         }
 
         try {
-            ICertRecord rec = mCertDB.readCertificateRecord(seq);
+            ICertRecord rec = certDB.readCertificateRecord(seq);
             if (rec == null) {
                 CMS.debug("DisplayBySerial: failed to read record");
                 throw new ECMSGWException(
@@ -461,12 +464,14 @@ public class DisplayBySerial extends CMSServlet {
         return;
     }
 
-    private ICertRecord getCertRecord(BigInteger seq, String certtype[])
+    private ICertRecord getCertRecord(
+            ICertificateRepository certDB,
+            BigInteger seq, String certtype[])
             throws EBaseException {
         ICertRecord rec = null;
 
         try {
-            rec = mCertDB.readCertificateRecord(seq);
+            rec = certDB.readCertificateRecord(seq);
             X509CertImpl x509cert = rec.getCertificate();
 
             if (x509cert != null) {
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java b/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java
index 1788be3039d12280d573dc9209ae2dbff3b9efd1..395425a17f88c3da38f00fb73caf5e5a2e29ee98 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/DoRevoke.java
@@ -84,7 +84,6 @@ public class DoRevoke extends CMSServlet {
     private static final long serialVersionUID = 1693115906265904238L;
     private final static String TPL_FILE = "revocationResult.template";
 
-    private ICertificateRepository mCertDB = null;
     private String mFormPath = null;
     private IPublisherProcessor mPublisherProcessor = null;
     private int mTimeLimits = 30; /* in seconds */
@@ -103,9 +102,6 @@ public class DoRevoke extends CMSServlet {
         super.init(sc);
         mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
 
-        if (mAuthority instanceof ICertificateAuthority) {
-            mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
-        }
         if (mAuthority instanceof ICertAuthority) {
             mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
         }
@@ -375,6 +371,8 @@ public class DoRevoke extends CMSServlet {
         CMS.debug("DoRevoke: eeSerialNumber: " + eeSerialNumber);
         long startTime = CMS.getCurrentDate().getTime();
 
+        ICertificateAuthority targetCA = certAuthority.getSubCA(req.getParameter("caRef"));
+
         RevocationProcessor processor =
                 new RevocationProcessor(servletConfig.getServletName(), getLocale(req));
 
@@ -395,9 +393,9 @@ public class DoRevoke extends CMSServlet {
         X509Certificate clientCert = getSSLClientCertificate(req);
 
         if (mAuthority instanceof ICertificateAuthority) {
-            processor.setAuthority(certAuthority);
+            processor.setAuthority(targetCA);
 
-            if (certAuthority.noncesEnabled()) {
+            if (targetCA.noncesEnabled()) {
                 String nonces = req.getParameter("nonce");
                 if (nonces == null) {
                     throw new ForbiddenException("Missing nonce.");
@@ -418,7 +416,8 @@ public class DoRevoke extends CMSServlet {
 
             if (mAuthority instanceof ICertificateAuthority) {
 
-                Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll, totalRecordCount, mTimeLimits);
+                ICertificateRepository certDB = targetCA.getCertificateRepository();
+                Enumeration<ICertRecord> e = certDB.searchCertificates(revokeAll, totalRecordCount, mTimeLimits);
 
                 while (e != null && e.hasMoreElements()) {
                     ICertRecord targetRecord = e.nextElement();
@@ -441,7 +440,7 @@ public class DoRevoke extends CMSServlet {
 
                     try {
                         if (mAuthority instanceof ICertificateAuthority &&
-                            certAuthority.noncesEnabled() &&
+                            targetCA.noncesEnabled() &&
                             !processor.isMemberOfSubsystemGroup(clientCert)) {
                             // validate nonce for each certificate
                             Long nonce = nonceMap.get(targetRecord.getSerialNumber());
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
index ee56f01399aa701c18fde4701e0c635772298d3c..b1d2c0f0c95c0160d7b031d408cd09623e7cef2d 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java
@@ -30,6 +30,7 @@ import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
 import com.netscape.certsrv.base.SessionContext;
 import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.profile.IEnrollProfile;
 import com.netscape.certsrv.profile.IProfile;
 import com.netscape.certsrv.profile.IProfileAuthenticator;
 import com.netscape.certsrv.profile.IProfileContext;
@@ -145,6 +146,12 @@ public class EnrollmentProcessor extends CertProcessor {
             }
 
             IProfileContext ctx = profile.createContext();
+
+            // insert request path into profile context
+            // (it is used to determine the (sub-)CA.
+            //
+            ctx.set(IEnrollProfile.REQUEST_AUTHORITY_REF, request.getParameter("caRef"));
+
             CMS.debug("EnrollmentSubmitter: set Inputs into profile Context");
             setInputsIntoContext(data, profile, ctx);
 
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
index 185e1fa8e7d24afdde7c4735722609921c6800ea..044a4571b4b62e61b70a90ab5bc171634b266b97 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ListCerts.java
@@ -74,8 +74,6 @@ public class ListCerts extends CMSServlet {
     private final static String USE_CLIENT_FILTER = "useClientFilter";
     private final static String ALLOWED_CLIENT_FILTERS = "allowedClientFilters";
 
-    private ICertificateRepository mCertDB = null;
-    private X500Name mAuthName = null;
     private String mFormPath = null;
     private boolean mReverse = false;
     private boolean mHardJumpTo = false; //jump to the end
@@ -102,13 +100,6 @@ public class ListCerts extends CMSServlet {
         // override success to render own template.
         mTemplates.remove(ICMSRequest.SUCCESS);
 
-        if (mAuthority instanceof ICertificateAuthority) {
-            ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
-
-            mCertDB = ca.getCertificateRepository();
-            mAuthName = ca.getX500Name();
-        }
-
         mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
         if (mOutputTemplatePath != null)
             mFormPath = mOutputTemplatePath;
@@ -390,7 +381,10 @@ public class ListCerts extends CMSServlet {
         } else
             pSize = maxCount;
 
-        ICertRecordList list = mCertDB.findCertRecordsInList(
+        ICertificateAuthority targetCA = certAuthority.getSubCA(req.getParameter("caRef"));
+        ICertificateRepository certDB = targetCA.getCertificateRepository();
+
+        ICertRecordList list = certDB.findCertRecordsInList(
                 filter, (String[]) null, jumpTo, mHardJumpTo, "serialno",
                 pSize);
         // retrive maxCount + 1 entries
@@ -403,7 +397,7 @@ public class ListCerts extends CMSServlet {
         if (!serialToVal.equals(MINUS_ONE)) {
             // if user specify a range, we need to
             // calculate the totalRecordCount
-            tolist = mCertDB.findCertRecordsInList(
+            tolist = certDB.findCertRecordsInList(
                         filter,
                         (String[]) null, serialTo,
                         "serialno", maxCount);
@@ -509,11 +503,14 @@ public class ListCerts extends CMSServlet {
             nextRec = e.nextElement();
         }
 
+        header.addStringValue("caRef", req.getParameter("caRef"));
         header.addStringValue("op", req.getParameter("op"));
         if (revokeAll != null)
             header.addStringValue("revokeAll", revokeAll);
-        if (mAuthName != null)
-            header.addStringValue("issuerName", mAuthName.toString());
+
+        X500Name issuerName = targetCA.getX500Name();
+        if (issuerName != null)
+            header.addStringValue("issuerName", issuerName.toString());
         if (!serialToVal.equals(MINUS_ONE))
             header.addStringValue("serialTo", serialToVal.toString());
         header.addStringValue("serviceURL", req.getRequestURI());
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java b/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
index c65c482b14a8670c2f87274d4194c9a40b883c68..3e3db1fec30cadfbfc9a81ca5169e19be1e85862 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
@@ -65,7 +65,6 @@ public class ReasonToRevoke extends CMSServlet {
     private final static String TPL_FILE = "reasonToRevoke.template";
     private final static String INFO = "ReasonToRevoke";
 
-    private ICertificateRepository mCertDB = null;
     private String mFormPath = null;
     private ICertificateAuthority mCA = null;
     private Random mRandom = null;
@@ -84,10 +83,8 @@ public class ReasonToRevoke extends CMSServlet {
     public void init(ServletConfig sc) throws ServletException {
         super.init(sc);
         mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
-        if (mAuthority instanceof ICertificateAuthority) {
+        if (mAuthority instanceof ICertificateAuthority)
             mCA = (ICertificateAuthority) mAuthority;
-            mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
-        }
 
         if (mCA != null && mCA.noncesEnabled()) {
             mRandom = new Random();
@@ -221,6 +218,7 @@ public class ReasonToRevoke extends CMSServlet {
             Locale locale)
             throws EBaseException {
 
+        header.addStringValue("caRef", req.getParameter("caRef"));
         header.addStringValue("revokeAll", revokeAll);
         header.addIntegerValue("totalRecordCount", totalRecordCount);
 
@@ -234,12 +232,15 @@ public class ReasonToRevoke extends CMSServlet {
                 }
             }
 
+            ICertificateAuthority targetCA = mCA.getSubCA(req.getParameter("caRef"));
+            ICertificateRepository certDB = targetCA.getCertificateRepository();
+
             /**
-             * ICertRecordList list = mCertDB.findCertRecordsInList(
+             * ICertRecordList list = certDB.findCertRecordsInList(
              * revokeAll, null, totalRecordCount);
              * Enumeration e = list.getCertRecords(0, totalRecordCount - 1);
              **/
-            Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll,
+            Enumeration<ICertRecord> e = certDB.searchCertificates(revokeAll,
                     totalRecordCount, mTimeLimits);
 
             ArrayList<String> noncesList = new ArrayList<String>();
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java b/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java
index 508a8df70a3fc8401879907c62f1939dbb410722..66898cd5d7a83681d8ec3ec364c31eb63866d040 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/SrchCerts.java
@@ -78,8 +78,6 @@ public class SrchCerts extends CMSServlet {
     private final static String CURRENT_TIME = "currentTime";
     private final static int MAX_RESULTS = 1000;
 
-    private ICertificateRepository mCertDB = null;
-    private X500Name mAuthName = null;
     private String mFormPath = null;
     private int mMaxReturns = MAX_RESULTS;
     private int mTimeLimits = 30; /* in seconds */
@@ -115,12 +113,6 @@ public class SrchCerts extends CMSServlet {
                 }
             }
         }
-        if (mAuthority instanceof ICertificateAuthority) {
-            ICertificateAuthority ca = (ICertificateAuthority) mAuthority;
-
-            mCertDB = ca.getCertificateRepository();
-            mAuthName = ca.getX500Name();
-        }
 
         mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE;
 
@@ -548,7 +540,8 @@ public class SrchCerts extends CMSServlet {
                 timeLimit = Integer.parseInt(timeLimitStr);
 
             String queryCertFilter = buildFilter(req);
-            process(argSet, header, queryCertFilter,
+            ICertificateAuthority targetCA = certAuthority.getSubCA(req.getParameter("caRef"));
+            process(targetCA, argSet, header, queryCertFilter,
                     revokeAll, maxResults, timeLimit, req, resp, locale[0]);
         } catch (NumberFormatException e) {
             log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT"));
@@ -584,13 +577,16 @@ public class SrchCerts extends CMSServlet {
     /**
      * Process the key search.
      */
-    private void process(CMSTemplateParams argSet, IArgBlock header,
+    private void process(ICertificateAuthority ca,
+            CMSTemplateParams argSet, IArgBlock header,
             String filter, String revokeAll,
             int maxResults, int timeLimit,
             HttpServletRequest req, HttpServletResponse resp,
             Locale locale)
             throws EBaseException {
         try {
+            ICertificateRepository certDB = ca.getCertificateRepository();
+
             long startTime = CMS.getCurrentDate().getTime();
 
             if (filter.indexOf(CURRENT_TIME, 0) > -1) {
@@ -608,7 +604,7 @@ public class SrchCerts extends CMSServlet {
             }
             CMS.debug("Start searching ... "
                     + "filter=" + filter + " maxreturns=" + maxResults + " timelimit=" + timeLimit);
-            Enumeration<ICertRecord> e = mCertDB.searchCertificates(filter, maxResults, timeLimit);
+            Enumeration<ICertRecord> e = certDB.searchCertificates(filter, maxResults, timeLimit);
 
             int count = 0;
 
@@ -626,9 +622,11 @@ public class SrchCerts extends CMSServlet {
 
             long endTime = CMS.getCurrentDate().getTime();
 
+            header.addStringValue("caRef", req.getParameter("caRef"));
             header.addStringValue("op", req.getParameter("op"));
-            if (mAuthName != null)
-                header.addStringValue("issuerName", mAuthName.toString());
+            X500Name issuerName = ca.getX500Name();
+            if (issuerName != null)
+                header.addStringValue("issuerName", issuerName.toString());
             header.addStringValue("time", Long.toString(endTime - startTime));
             header.addStringValue("serviceURL", req.getRequestURI());
             header.addStringValue("queryFilter", filter);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java b/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java
index 940bf657c6febdb9ec01757daa2f1a49ac2ee2be..77554ea24513635e37304a3b8870698c0f3e845d 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java
@@ -35,6 +35,7 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.authentication.IAuthToken;
 import com.netscape.certsrv.authorization.AuthzToken;
 import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.common.ICMSRequest;
 import com.netscape.certsrv.ocsp.IOCSPService;
 import com.netscape.certsrv.util.IStatsSubsystem;
@@ -204,7 +205,9 @@ public class OCSPServlet extends CMSServlet {
                     throw new Exception("OCSPServlet: Decoded OCSP request "
                                        + "is empty or malformed");
                 }
-                response = ((IOCSPService) mAuthority).validate(ocspReq);
+                ICertificateAuthority targetCA =
+                    certAuthority.getSubCA(httpReq.getParameter("caRef"));
+                response = ((IOCSPService) targetCA).validate(ocspReq);
             } catch (Exception e) {
                 ;
                 CMS.debug("OCSPServlet: " + e.toString());
-- 
2.1.0



More information about the Pki-devel mailing list