[Pki-devel] [PATCH] 0026 Add lightweight sub-CA support
Fraser Tweedale
ftweedal at redhat.com
Thu May 7 04:36:03 UTC 2015
Please find updated sub-CA patch that adds subca management REST API
and CLI commands, and sub-CA creation. There is still more work to
do so I am not looking for ACKs right now, but I would like review
in particular of the sub-CA creation routine.
Dogtag web UI for selecting a sub-CA is deferred so if you want to
send issuance/revocation requests to a sub-CA you will still need to
(from earlier mail):
> 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.)
Cheers,
Fraser
-------------- next part --------------
>From 297fa7b80677c36baf595cba1bacbdd398590acf Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
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 | 8 +-
.../shared/webapps/ca/agent/ca/srchCert.template | 2 +
base/ca/shared/webapps/ca/ee/ca/queryCert.template | 6 +-
.../webapps/ca/ee/ca/reasonToRevoke.template | 8 +-
.../src/com/netscape/ca/CertificateAuthority.java | 169 ++++++++++++++++++++-
base/ca/src/com/netscape/ca/SigningUnit.java | 10 +-
.../dogtagpki/server/ca/rest/CAApplication.java | 3 +
.../org/dogtagpki/server/ca/rest/SubCAService.java | 165 ++++++++++++++++++++
.../src/com/netscape/certsrv/ca/CAClient.java | 3 +-
.../netscape/certsrv/ca/ICertificateAuthority.java | 28 ++++
.../netscape/certsrv/profile/IEnrollProfile.java | 5 +
.../netscape/certsrv/security/ISigningUnit.java | 8 +
.../src/com/netscape/certsrv/subca/CAData.java | 88 +++++++++++
.../com/netscape/certsrv/subca/SubCAClient.java | 49 ++++++
.../com/netscape/certsrv/subca/SubCAResource.java | 29 ++++
.../src/com/netscape/cmstools/cli/CACLI.java | 2 +
.../src/com/netscape/cmstools/subca/SubCACLI.java | 51 +++++++
.../netscape/cmstools/subca/SubCACreateCLI.java | 66 ++++++++
.../com/netscape/cmstools/subca/SubCAShowCLI.java | 57 +++++++
.../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 | 9 ++
.../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/csadmin/CertUtil.java | 38 +++--
.../com/netscape/cms/servlet/ocsp/OCSPServlet.java | 5 +-
33 files changed, 874 insertions(+), 89 deletions(-)
create mode 100644 base/ca/src/org/dogtagpki/server/ca/rest/SubCAService.java
create mode 100644 base/common/src/com/netscape/certsrv/subca/CAData.java
create mode 100644 base/common/src/com/netscape/certsrv/subca/SubCAClient.java
create mode 100644 base/common/src/com/netscape/certsrv/subca/SubCAResource.java
create mode 100644 base/java-tools/src/com/netscape/cmstools/subca/SubCACLI.java
create mode 100644 base/java-tools/src/com/netscape/cmstools/subca/SubCACreateCLI.java
create mode 100644 base/java-tools/src/com/netscape/cmstools/subca/SubCAShowCLI.java
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..711592a4e463b6e791587644da4233af08e93cca 100644
--- a/base/ca/shared/webapps/ca/agent/ca/reasonToRevoke.template
+++ b/base/ca/shared/webapps/ca/agent/ca/reasonToRevoke.template
@@ -193,9 +193,9 @@ function displayCertInfo()
document.write("<table border=\"0\" cellspacing=\"2\">");
for (var i = 0; i < result.recordSet.length; ++i ) {
if (result.recordSet[i].serialNumber != null) {
- if (result.header.caSerialNumber != null &&
- result.recordSet[i].serialNumber ==
- result.header.caSerialNumber) {
+ if (result.header.caSerialNumber != null
+ && result.recordSet[i].serialNumber == result.header.caSerialNumber
+ && (result.header.caRef || "") == "") {
document.write(renderRowWithoutCheckbox("Serial Number:",
toHex(result.recordSet[i].serialNumber)));
} else {
@@ -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..d81e37a1dab30b079fcbb82c19f6a8ec940deb46 100644
--- a/base/ca/shared/webapps/ca/ee/ca/reasonToRevoke.template
+++ b/base/ca/shared/webapps/ca/ee/ca/reasonToRevoke.template
@@ -187,9 +187,9 @@ function displayCertInfo()
document.write("<table border=\"0\" cellspacing=\"2\">");
for (var i = 0; i < result.recordSet.length; ++i ) {
if (result.recordSet[i].serialNumber != null) {
- if (result.header.caSerialNumber != null &&
- result.recordSet[i].serialNumber ==
- result.header.caSerialNumber) {
+ if (result.header.caSerialNumber != null
+ && result.recordSet[i].serialNumber == result.header.caSerialNumber
+ && (result.header.caRef || "") == "") {
document.write(renderRowWithoutCheckbox("Serial Number: ",
toHex(result.recordSet[i].serialNumber)));
} else {
@@ -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..bd32433fab67ddfa88e4b3f0da2a710896009161 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -25,14 +25,17 @@ import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.KeyPair;
import java.security.PublicKey;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
+import java.util.ArrayList;
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;
@@ -60,6 +63,9 @@ import org.mozilla.jss.asn1.INTEGER;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.asn1.OCTET_STRING;
+import org.mozilla.jss.crypto.CryptoToken;
+import org.mozilla.jss.crypto.KeyPairAlgorithm;
+import org.mozilla.jss.crypto.KeyPairGenerator;
import org.mozilla.jss.crypto.SignatureAlgorithm;
import org.mozilla.jss.crypto.TokenException;
import org.mozilla.jss.pkix.cert.Extension;
@@ -77,6 +83,7 @@ import com.netscape.certsrv.ca.ECAException;
import com.netscape.certsrv.ca.ICRLIssuingPoint;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.IDBSubsystem;
+import com.netscape.certsrv.dbs.IDBSSession;
import com.netscape.certsrv.dbs.certdb.ICertRecord;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
import com.netscape.certsrv.dbs.crldb.ICRLRepository;
@@ -96,6 +103,8 @@ import com.netscape.certsrv.request.IRequestScheduler;
import com.netscape.certsrv.request.IService;
import com.netscape.certsrv.security.ISigningUnit;
import com.netscape.certsrv.util.IStatsSubsystem;
+import com.netscape.cms.servlet.csadmin.CertUtil;
+import com.netscape.cmscore.base.PropConfigStore;
import com.netscape.cmscore.dbs.CRLRepository;
import com.netscape.cmscore.dbs.CertRecord;
import com.netscape.cmscore.dbs.CertificateRepository;
@@ -106,6 +115,7 @@ import com.netscape.cmscore.listeners.ListenerPlugin;
import com.netscape.cmscore.request.RequestSubsystem;
import com.netscape.cmscore.security.KeyCertUtil;
import com.netscape.cmscore.util.Debug;
+import com.netscape.cmsutil.crypto.CryptoUtil;
import com.netscape.cmsutil.ocsp.BasicOCSPResponse;
import com.netscape.cmsutil.ocsp.CertID;
import com.netscape.cmsutil.ocsp.CertStatus;
@@ -123,6 +133,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 +149,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 +250,27 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
* Constructs a CA subsystem.
*/
public CertificateAuthority() {
+ subCAHier = new ArrayList(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 +1263,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 +1343,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 +1490,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 +2131,121 @@ 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, "/");
+ List<String> path = new ArrayList(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 ArrayList();
+ 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;
+ }
+
+ /**
+ * Create a new sub-CA directly underneath this CA.
+ */
+ public ICertificateAuthority createSubCA(String handle, String dn)
+ throws EBaseException {
+ ICertificateAuthority target = null;
+ try {
+ target = getSubCA(handle);
+ } catch (Exception e) {
+ // squash it; this is normal
+ }
+ if (target != null)
+ throw new ECAException("Sub-CA already exists" /* TODO getUserMessage */);
+
+ ArrayList<String> hier = new ArrayList<>(subCAHier);
+ hier.add(handle);
+
+ try {
+ /*
+ * Generate sub-CA signing key
+ */
+ CryptoManager cryptoManager = CryptoManager.getInstance();
+ // TODO read PROP_TOKEN_NAME config
+ CryptoToken token = cryptoManager.getInternalKeyStorageToken();
+ // TODO algorithm parameter
+ KeyPairGenerator gen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA);
+ gen.initialize(2048);
+ KeyPair keypair = gen.genKeyPair();
+ PublicKey pub = keypair.getPublic();
+ X509Key x509key = CryptoUtil.convertPublicKeyToX509Key(pub);
+
+ /*
+ * Sign certificate
+ */
+ String algName = mSigningUnit.getDefaultAlgorithm();
+ IConfigStore cs = new PropConfigStore("cs");
+ cs.put(".profile", "caCert.profile");
+ cs.put(".dn", dn);
+ cs.put(".keyalgorithm", algName);
+ X509CertImpl cert =
+ CertUtil.createLocalCertWithCA(cs, x509key, "", "", "local", this);
+
+ /*
+ * Add certificate to nssdb
+ */
+ IConfigStore sigCS = mConfig.getSubStore(PROP_SIGNING_SUBSTORE);
+ String topNick = null;
+ try {
+ topNick = sigCS.getString(ISigningUnit.PROP_RENAMED_CERT_NICKNAME);
+ } catch (EBaseException e) {
+ topNick = sigCS.getString(ISigningUnit.PROP_CERT_NICKNAME);
+ }
+ String nickname = topNick + " " + StringUtils.join(hier, ",");
+ cryptoManager.importCertPackage(cert.getEncoded(), nickname);
+ } catch (Exception e) {
+ throw new ECAException("Error creating sub-CA certificate" /* TODO getUserMessage */);
+ }
+
+ /*
+ * Create LDAP entries
+ */
+ String certReposDN = joinSubCAOUs(hier) +
+ "ou=certificateRepository, ou=" + getId() + ", " + getDBSubsystem().getBaseDN();
+ try (IDBSSession s = DBSubsystem.getInstance().createSession()) {
+ s.add(certReposDN, CMS.createRepositoryRecord());
+ }
+
+ return getSubCA(handle);
+ }
}
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/ca/src/org/dogtagpki/server/ca/rest/CAApplication.java b/base/ca/src/org/dogtagpki/server/ca/rest/CAApplication.java
index 8c6c8cbe54df366a807463f23790eb84ccc30c68..785244f4b9d6b1ad63a5b3294167ef362d29f0d1 100644
--- a/base/ca/src/org/dogtagpki/server/ca/rest/CAApplication.java
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/CAApplication.java
@@ -38,6 +38,9 @@ public class CAApplication extends Application {
// installer
classes.add(CAInstallerService.class);
+ // sub-ca management
+ classes.add(SubCAService.class);
+
// certs and requests
classes.add(CertService.class);
classes.add(CertRequestService.class);
diff --git a/base/ca/src/org/dogtagpki/server/ca/rest/SubCAService.java b/base/ca/src/org/dogtagpki/server/ca/rest/SubCAService.java
new file mode 100644
index 0000000000000000000000000000000000000000..77939929b22ac18786b8020428ecdfefba126c9a
--- /dev/null
+++ b/base/ca/src/org/dogtagpki/server/ca/rest/SubCAService.java
@@ -0,0 +1,165 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2015 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+
+package org.dogtagpki.server.ca.rest;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.commons.lang.StringUtils;
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.BadRequestException;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
+import com.netscape.certsrv.common.NameValuePairs;
+import com.netscape.certsrv.common.OpDef;
+import com.netscape.certsrv.common.ScopeDef;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.subca.CAData;
+import com.netscape.certsrv.subca.SubCAResource;
+import com.netscape.cms.realm.PKIPrincipal;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author ftweedal
+ */
+public class SubCAService extends PKIService implements SubCAResource {
+
+ ICertificateAuthority topCA;
+
+ public SubCAService() {
+ topCA = (ICertificateAuthority) CMS.getSubsystem("ca");
+ }
+
+ @Context
+ private UriInfo uriInfo;
+
+ @Context
+ private HttpHeaders headers;
+
+ @Context
+ private Request request;
+
+ @Context
+ private HttpServletRequest servletRequest;
+
+ /*
+ private final static String LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL =
+ "LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL_4";
+ private final static String LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE =
+ "LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE_3";
+ */
+
+ @Override
+ public Response getCA(String caRef) {
+ ICertificateAuthority ca = null;
+ boolean noSuchCA = false;
+ try {
+ ca = topCA.getSubCA(caRef);
+ } catch (EBaseException e) {
+ noSuchCA = true;
+ }
+ if (noSuchCA || ca == null)
+ throw new BadRequestException("CA \"" + caRef + "\" does not exist");
+
+ return createOKResponse(readCAData(caRef, ca));
+ }
+
+ @Override
+ public Response createCA(CAData data) {
+ // splice final part off caRef
+ String caRef = data.getCARef();
+
+ caRef = StringUtils.strip(caRef, " /");
+ String[] components = StringUtils.split(caRef, "/");
+ List<String> parentPath = new ArrayList<>();
+ for (int i = 0; i < components.length - 1; i++)
+ parentPath.add(components[i]);
+ String caHandle = components[components.length - 1];
+
+ ICertificateAuthority parentCA = null;
+ try {
+ parentCA = topCA.getSubCA(parentPath);
+ } catch (EBaseException e) {
+ throw new BadRequestException("Parent CA \""
+ + StringUtils.join(parentPath, '/')
+ + "\" does not exist");
+ }
+
+ ICertificateAuthority subCA = null;
+ try {
+ subCA = parentCA.createSubCA(caHandle, data.getDN());
+ } catch (Exception e) {
+ // TODO catch more specific exception
+ CMS.debug(e);
+ throw new PKIException("Error creating sub-CA: " + e.toString());
+ }
+
+ return createOKResponse(readCAData(caRef, subCA));
+ }
+
+ private static CAData readCAData(String caRef, ICertificateAuthority ca)
+ throws PKIException {
+ String dn;
+ try {
+ dn = ca.getX500Name().toLdapDNString();
+ } catch (IOException e) {
+ throw new PKIException("Error reading CA data: could not determine Issuer DN");
+ }
+
+ return new CAData(caRef, dn);
+ }
+
+ /* TODO work out what audit messages are needed
+ public void auditProfileChangeState(String profileId, String op, String status) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL,
+ auditor.getSubjectID(),
+ status,
+ profileId,
+ op);
+ auditor.log(msg);
+ }
+
+ public void auditProfileChange(String scope, String type, String id, String status, Map<String, String> params) {
+ String msg = CMS.getLogMessage(
+ LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE,
+ auditor.getSubjectID(),
+ status,
+ auditor.getParamString(scope, type, id, params));
+ auditor.log(msg);
+ }
+ */
+
+}
diff --git a/base/common/src/com/netscape/certsrv/ca/CAClient.java b/base/common/src/com/netscape/certsrv/ca/CAClient.java
index ff5a0e21491b40649f04cd9ce701041c2b795b14..170698b0cf04d8b6eded9721f1e85018de01286b 100644
--- a/base/common/src/com/netscape/certsrv/ca/CAClient.java
+++ b/base/common/src/com/netscape/certsrv/ca/CAClient.java
@@ -27,6 +27,7 @@ import com.netscape.certsrv.logging.AuditClient;
import com.netscape.certsrv.profile.ProfileClient;
import com.netscape.certsrv.selftests.SelfTestClient;
import com.netscape.certsrv.user.UserClient;
+import com.netscape.certsrv.subca.SubCAClient;
public class CAClient extends SubsystemClient {
@@ -36,7 +37,7 @@ public class CAClient extends SubsystemClient {
}
public void init() throws URISyntaxException {
-
+ addClient(new SubCAClient(client, name));
addClient(new AuditClient(client, name));
addClient(new CertClient(client, name));
addClient(new GroupClient(client, name));
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index f87f15420b3ea6e02e5ce47b5c350e86f67ccc9f..3e65eac6e1e71649517cd1850a26aad2959dfd8d 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,31 @@ 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;
+
+ /**
+ * Create a new sub-CA directly underneath this CA.
+ *
+ * Return the new certificate authority or null on error.
+ *
+ * @param handle The individual handle of the sub-CA' _not_ a
+ * complete caRef
+ */
+ public ICertificateAuthority createSubCA(String handle, String dn)
+ throws Exception;
}
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/common/src/com/netscape/certsrv/security/ISigningUnit.java b/base/common/src/com/netscape/certsrv/security/ISigningUnit.java
index 34d2a5109170c560b5a449d08f43eeeda5035b88..75b45bb8b31cde22881e0ddc310c0bdb51a66338 100644
--- a/base/common/src/com/netscape/certsrv/security/ISigningUnit.java
+++ b/base/common/src/com/netscape/certsrv/security/ISigningUnit.java
@@ -17,6 +17,7 @@
// --- END COPYRIGHT BLOCK ---
package com.netscape.certsrv.security;
+import java.security.PrivateKey;
import java.security.PublicKey;
import netscape.security.x509.X509CertImpl;
@@ -161,4 +162,11 @@ public interface ISigningUnit {
* @return public key
*/
public PublicKey getPublicKey();
+
+ /**
+ * Retrieves the public key associated in this unit.
+ *
+ * @return public key
+ */
+ public PrivateKey getPrivateKey();
}
diff --git a/base/common/src/com/netscape/certsrv/subca/CAData.java b/base/common/src/com/netscape/certsrv/subca/CAData.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2482b877b22bcaa830032b51660ed67bf61d7d8
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/subca/CAData.java
@@ -0,0 +1,88 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2015 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+/**
+ * @author ftweedal
+ */
+package com.netscape.certsrv.subca;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.jboss.resteasy.plugins.providers.atom.Link;
+
+ at XmlRootElement(name = "ca")
+ at XmlAccessorType(XmlAccessType.FIELD)
+public class CAData {
+
+ public static Marshaller marshaller;
+ public static Unmarshaller unmarshaller;
+
+ static {
+ try {
+ marshaller = JAXBContext.newInstance(CAData.class).createMarshaller();
+ marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+ unmarshaller = JAXBContext.newInstance(CAData.class).createUnmarshaller();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ @XmlAttribute
+ protected String caRef;
+
+ public String getCARef() {
+ return caRef;
+ }
+
+ @XmlAttribute
+ protected String dn;
+
+ public String getDN() {
+ return dn;
+ }
+
+
+ protected Link link;
+
+ public Link getLink() {
+ return link;
+ }
+
+ public void setLink(Link link) {
+ this.link = link;
+ }
+
+ protected CAData() {
+ }
+
+ public CAData(String caRef, String dn) {
+ this.caRef = caRef;
+ this.dn = dn;
+ }
+
+}
diff --git a/base/common/src/com/netscape/certsrv/subca/SubCAClient.java b/base/common/src/com/netscape/certsrv/subca/SubCAClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..de4789771fbce7d722aefa3041f6c6773a4e664b
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/subca/SubCAClient.java
@@ -0,0 +1,49 @@
+//--- BEGIN COPYRIGHT BLOCK ---
+//This program is free software; you can redistribute it and/or modify
+//it under the terms of the GNU General Public License as published by
+//the Free Software Foundation; version 2 of the License.
+//
+//This program is distributed in the hope that it will be useful,
+//but WITHOUT ANY WARRANTY; without even the implied warranty of
+//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//GNU General Public License for more details.
+//
+//You should have received a copy of the GNU General Public License along
+//with this program; if not, write to the Free Software Foundation, Inc.,
+//51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+//(C) 2015 Red Hat, Inc.
+//All rights reserved.
+//--- END COPYRIGHT BLOCK ---
+package com.netscape.certsrv.subca;
+
+import java.net.URISyntaxException;
+
+import javax.ws.rs.core.Response;
+
+import com.netscape.certsrv.client.Client;
+import com.netscape.certsrv.client.PKIClient;
+
+/**
+ * @author Fraser Tweedale <ftweedal at redhat.com>
+ */
+public class SubCAClient extends Client {
+
+ public SubCAResource proxy;
+
+ public SubCAClient(PKIClient client, String subsystem) throws URISyntaxException {
+ super(client, subsystem, "subca");
+ proxy = createProxy(SubCAResource.class);
+ }
+
+ public CAData getCA(String caRef) {
+ Response response = proxy.getCA(caRef);
+ return client.getEntity(response, CAData.class);
+ }
+
+ public CAData createCA(CAData data) {
+ Response response = proxy.createCA(data);
+ return client.getEntity(response, CAData.class);
+ }
+
+}
diff --git a/base/common/src/com/netscape/certsrv/subca/SubCAResource.java b/base/common/src/com/netscape/certsrv/subca/SubCAResource.java
new file mode 100644
index 0000000000000000000000000000000000000000..0bb1ff87c903f6c23481d398293bd59b26e7d0f0
--- /dev/null
+++ b/base/common/src/com/netscape/certsrv/subca/SubCAResource.java
@@ -0,0 +1,29 @@
+package com.netscape.certsrv.subca;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+
+import org.jboss.resteasy.annotations.ClientResponseType;
+
+import com.netscape.certsrv.acls.ACLMapping;
+import com.netscape.certsrv.authentication.AuthMethodMapping;
+
+ at Path("subca")
+public interface SubCAResource {
+
+ @GET
+ @Path("{caRef}")
+ @ClientResponseType(entityType=CAData.class)
+ public Response getCA(@PathParam("caRef") String caRef);
+
+ @POST
+ @ClientResponseType(entityType=CAData.class)
+ //@ACLMapping("certs")
+ //@AuthMethodMapping("certs")
+ public Response createCA(CAData data);
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java b/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
index 3cb456e5feddd6ca1bee312f21c9fc55269c5143..7351345f39e6ff603bd27616144627452161a20b 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/CACLI.java
@@ -25,6 +25,7 @@ import com.netscape.cmstools.group.GroupCLI;
import com.netscape.cmstools.logging.AuditCLI;
import com.netscape.cmstools.profile.ProfileCLI;
import com.netscape.cmstools.selftests.SelfTestCLI;
+import com.netscape.cmstools.subca.SubCACLI;
import com.netscape.cmstools.system.KRAConnectorCLI;
import com.netscape.cmstools.user.UserCLI;
@@ -39,6 +40,7 @@ public class CACLI extends SubsystemCLI {
super("ca", "CA management commands", parent);
addModule(new AuditCLI(this));
+ addModule(new SubCACLI(this));
addModule(new CertCLI(this));
addModule(new GroupCLI(this));
addModule(new KRAConnectorCLI(this));
diff --git a/base/java-tools/src/com/netscape/cmstools/subca/SubCACLI.java b/base/java-tools/src/com/netscape/cmstools/subca/SubCACLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1833834133ed1e8e1ac468c8f1895b3b98b45f9
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/subca/SubCACLI.java
@@ -0,0 +1,51 @@
+package com.netscape.cmstools.subca;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.net.URI;
+import java.util.Locale;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import com.netscape.certsrv.cert.CertEnrollmentRequest;
+import com.netscape.certsrv.subca.CAData;
+import com.netscape.certsrv.subca.SubCAClient;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class SubCACLI extends CLI {
+
+ public SubCAClient subcaClient;
+
+ public SubCACLI(CLI parent) {
+ super("subca", "Sub-CA management commands", parent);
+
+ addModule(new SubCAShowCLI(this));
+ addModule(new SubCACreateCLI(this));
+ }
+
+ public String getFullName() {
+ if (parent instanceof MainCLI) {
+ // do not include MainCLI's name
+ return name;
+ } else {
+ return parent.getFullName() + "-" + name;
+ }
+ }
+
+ public void execute(String[] args) throws Exception {
+ client = parent.getClient();
+ subcaClient = new SubCAClient(client, "ca");
+ super.execute(args);
+ }
+
+ protected static void printCAData(CAData data) {
+ System.out.println(" CA handle: " + data.getCARef());
+ System.out.println(" Issuer DN: " + data.getDN());
+ }
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/subca/SubCACreateCLI.java b/base/java-tools/src/com/netscape/cmstools/subca/SubCACreateCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..7a1f7ad08addc77103bb2d32c94ff5a7c5c6b737
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/subca/SubCACreateCLI.java
@@ -0,0 +1,66 @@
+package com.netscape.cmstools.subca;
+
+import java.util.Arrays;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.ParseException;
+
+import com.netscape.certsrv.subca.CAData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class SubCACreateCLI extends CLI {
+
+ public SubCACLI subcaCLI;
+
+ public SubCACreateCLI(SubCACLI subcaCLI) {
+ super("create", "Create sub-CAs", subcaCLI);
+ this.subcaCLI = subcaCLI;
+ }
+
+ public void printHelp() {
+ formatter.printHelp(getFullName() + " <handle> <dn>", options);
+ }
+
+ public void execute(String[] args) throws Exception {
+ // Always check for "--help" prior to parsing
+ if (Arrays.asList(args).contains("--help")) {
+ // Display usage
+ printHelp();
+ System.exit(0);
+ }
+
+ CommandLine cmd = null;
+
+ try {
+ cmd = parser.parse(options, args);
+ } catch (ParseException e) {
+ System.err.println("Error: " + e.getMessage());
+ printHelp();
+ System.exit(-1);
+ }
+
+ String[] cmdArgs = cmd.getArgs();
+
+ String[] positionalArgNames = {
+ "CA handle",
+ "Issuer DN"
+ };
+
+ if (cmdArgs.length < positionalArgNames.length) {
+ System.err.println("Error: No "
+ + positionalArgNames[cmdArgs.length]
+ + " specified.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ String caRef = cmdArgs[0];
+ String dn = cmdArgs[1];
+ CAData data = new CAData(caRef, dn);
+ CAData newData = subcaCLI.subcaClient.createCA(data);
+ SubCACLI.printCAData(newData);
+ }
+
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/subca/SubCAShowCLI.java b/base/java-tools/src/com/netscape/cmstools/subca/SubCAShowCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..e05ab84259b438d2df97880ef96a3aa694a2ba0e
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/subca/SubCAShowCLI.java
@@ -0,0 +1,57 @@
+package com.netscape.cmstools.subca;
+
+import java.util.Arrays;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.ParseException;
+
+import com.netscape.certsrv.subca.CAData;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+public class SubCAShowCLI extends CLI {
+
+ public SubCACLI subcaCLI;
+
+ public SubCAShowCLI(SubCACLI subcaCLI) {
+ super("show", "Show sub-CAs", subcaCLI);
+ this.subcaCLI = subcaCLI;
+ }
+
+ public void printHelp() {
+ formatter.printHelp(getFullName() + " <caRef>", options);
+ }
+
+ public void execute(String[] args) throws Exception {
+ // Always check for "--help" prior to parsing
+ if (Arrays.asList(args).contains("--help")) {
+ // Display usage
+ printHelp();
+ System.exit(0);
+ }
+
+ CommandLine cmd = null;
+
+ try {
+ cmd = parser.parse(options, args);
+ } catch (ParseException e) {
+ System.err.println("Error: " + e.getMessage());
+ printHelp();
+ System.exit(-1);
+ }
+
+ String[] cmdArgs = cmd.getArgs();
+
+ if (cmdArgs.length < 1) {
+ System.err.println("Error: No caRef specified.");
+ printHelp();
+ System.exit(-1);
+ }
+
+ String caRef = cmdArgs[0];
+ CAData data = subcaCLI.subcaClient.getCA(caRef);
+ SubCACLI.printCAData(data);
+ }
+
+}
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 fe3b424a4b8e13215d4029d328d4a1e280be63ff..36938ab8f927dbf98804b0c833b65604c884b213 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
@@ -190,6 +190,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 095f8bb5ffa2f950b58c868a6daee99991a80daa..ce01973403a7bb2ae87b8b8c3b71a48afba332ed 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..b0034d2d795dc34b76a2324b9bfe22d68054c9e9 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,14 @@ public class EnrollmentProcessor extends CertProcessor {
}
IProfileContext ctx = profile.createContext();
+
+ // insert request path into profile context
+ // (it is used to determine the (sub-)CA.
+ //
+ String caRef = request.getParameter("caRef");
+ if (caRef != null)
+ ctx.set(IEnrollProfile.REQUEST_AUTHORITY_REF, 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/csadmin/CertUtil.java b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java
index 36b0e4d0d44ec8987856ebaaa3f4919c4a3f7071..c0729d88100e64d06c099bc4f1d73a14bcb9918f 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java
@@ -434,8 +434,19 @@ public class CertUtil {
(signingKeyType.equals("dsa") && algorithm.contains("DSA")));
}
+ public static X509CertImpl createLocalCertWithCA(IConfigStore config, X509Key x509key,
+ String prefix, String certTag, String type, ICertificateAuthority ca) throws IOException {
+ return createLocalCert(config, x509key, prefix, certTag, type, ca, null);
+ }
+
public static X509CertImpl createLocalCert(IConfigStore config, X509Key x509key,
String prefix, String certTag, String type, Context context) throws IOException {
+ return createLocalCert(config, x509key, prefix, certTag, type, null, context);
+ }
+
+ public static X509CertImpl createLocalCert(IConfigStore config, X509Key x509key,
+ String prefix, String certTag, String type,
+ ICertificateAuthority ca, Context context) throws IOException {
CMS.debug("Creating local certificate... certTag=" + certTag);
String profile = null;
@@ -446,13 +457,14 @@ public class CertUtil {
}
X509CertImpl cert = null;
- ICertificateAuthority ca = null;
ICertificateRepository cr = null;
RequestId reqId = null;
String profileId = null;
IRequestQueue queue = null;
IRequest req = null;
+ boolean caProvided = ca != null;
+
try {
Boolean injectSAN = config.getBoolean(
"service.injectSAN", false);
@@ -468,7 +480,8 @@ public class CertUtil {
} else {
keyAlgorithm = config.getString(prefix + certTag + ".keyalgorithm");
}
- ca = (ICertificateAuthority) CMS.getSubsystem(
+ if (!caProvided)
+ ca = (ICertificateAuthority) CMS.getSubsystem(
ICertificateAuthority.ID);
cr = ca.getCertificateRepository();
BigInteger serialNo = cr.getNextSerialNumber();
@@ -496,9 +509,9 @@ public class CertUtil {
}
CMS.debug("Cert Template: " + info.toString());
- String instanceRoot = config.getString("instanceRoot");
+ String instanceRoot = CMS.getConfigStore().getString("instanceRoot");
- String configurationRoot = config.getString("configurationRoot");
+ String configurationRoot = CMS.getConfigStore().getString("configurationRoot");
CertInfoProfile processor = new CertInfoProfile(
instanceRoot + configurationRoot + profile);
@@ -541,11 +554,18 @@ public class CertUtil {
processor.populate(req, info);
- String caPriKeyID = config.getString(
- prefix + "signing" + ".privkey.id");
- byte[] keyIDb = CryptoUtil.string2byte(caPriKeyID);
- PrivateKey caPrik = CryptoUtil.findPrivateKeyFromID(
- keyIDb);
+ PrivateKey caPrik = null;
+ if (caProvided) {
+ java.security.PrivateKey pk = ca.getSigningUnit().getPrivateKey();
+ if (!(pk instanceof PrivateKey))
+ throw new IOException("CA Private key must be a JSS PrivateKey");
+ caPrik = (PrivateKey) pk;
+ } else {
+ String caPriKeyID = config.getString(
+ prefix + "signing" + ".privkey.id");
+ byte[] keyIDb = CryptoUtil.string2byte(caPriKeyID);
+ caPrik = CryptoUtil.findPrivateKeyFromID(keyIDb);
+ }
if (caPrik == null) {
CMS.debug("CertUtil::createSelfSignedCert() - "
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