summaryrefslogtreecommitdiffstats
path: root/base/server/cms/src/com/netscape/cms
diff options
context:
space:
mode:
authorFraser Tweedale <ftweedal@redhat.com>2015-01-28 02:41:10 -0500
committerFraser Tweedale <ftweedal@redhat.com>2015-09-26 14:11:51 +1000
commit2a9f56d02b4a284cda6f8b61b250e1494f19a83e (patch)
tree9b12125932ed41a5dbe06f8dafb66656e78c7ad8 /base/server/cms/src/com/netscape/cms
parenta5a50e95a691587e22335018538b4f578dfee6d1 (diff)
downloadpki-2a9f56d02b4a284cda6f8b61b250e1494f19a83e.tar.gz
pki-2a9f56d02b4a284cda6f8b61b250e1494f19a83e.tar.xz
pki-2a9f56d02b4a284cda6f8b61b250e1494f19a83e.zip
Lightweight CAs: initial support
This commit adds initial support for "lightweight CAs" - CAs that inhabit an existing CA instance and share the request queue and certificate database of the "top-level CA". We initially support only sub-CAs under the top-level CA - either direct sub-CAs or nested. The general design will support hosting unrelated CAs but creation or import of unrelated CAs is not yet implemented. Part of: https://fedorahosted.org/pki/ticket/1213
Diffstat (limited to 'base/server/cms/src/com/netscape/cms')
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/CAEnrollProfile.java11
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/common/EnrollProfile.java3
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/AuthorityKeyIdentifierExtDefault.java30
-rw-r--r--base/server/cms/src/com/netscape/cms/profile/def/CAEnrollDefault.java4
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java5
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java2
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/EnrollmentProcessor.java15
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java36
-rw-r--r--base/server/cms/src/com/netscape/cms/servlet/csadmin/CertUtil.java38
9 files changed, 114 insertions, 30 deletions
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 d0bfdb8a6..53edca3a9 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
@@ -29,6 +29,7 @@ import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authority.IAuthority;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.SessionContext;
+import com.netscape.certsrv.ca.AuthorityID;
import com.netscape.certsrv.ca.ICAService;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.connector.IConnector;
@@ -95,8 +96,8 @@ public class CAEnrollProfile extends EnrollProfile {
CMS.debug("CAEnrollProfile: execute reqId=" +
request.getRequestId().toString());
ICertificateAuthority ca = (ICertificateAuthority) getAuthority();
- ICAService caService = (ICAService) ca.getCAService();
+ ICAService caService = (ICAService) ca.getCAService();
if (caService == null) {
throw new EProfileException("No CA Service");
}
@@ -190,9 +191,13 @@ public class CAEnrollProfile extends EnrollProfile {
if (setId != null) {
sc.put("profileSetId", setId);
}
+ AuthorityID aid = null;
+ String aidString = request.getExtDataInString(REQUEST_AUTHORITY_ID);
+ if (aidString != null)
+ aid = new AuthorityID(aidString);
try {
- theCert = caService.issueX509Cert(info, getId() /* profileId */,
- id /* requestId */);
+ theCert = caService.issueX509Cert(
+ aid, info, getId() /* profileId */, id /* requestId */);
} catch (EBaseException e) {
CMS.debug(e.toString());
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 fe3b424a4..523e0117a 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_ID, ctx.get(REQUEST_AUTHORITY_ID));
}
return result;
}
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 095f8bb5f..bd71a4ef8 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
@@ -20,20 +20,23 @@ package com.netscape.cms.profile.def;
import java.io.IOException;
import java.util.Locale;
-import netscape.security.x509.AuthorityKeyIdentifierExtension;
-import netscape.security.x509.KeyIdentifier;
-import netscape.security.x509.PKIXExtensions;
-import netscape.security.x509.X509CertInfo;
-
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.AuthorityID;
+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;
import com.netscape.certsrv.property.IDescriptor;
import com.netscape.certsrv.request.IRequest;
+import netscape.security.x509.AuthorityKeyIdentifierExtension;
+import netscape.security.x509.KeyIdentifier;
+import netscape.security.x509.PKIXExtensions;
+import netscape.security.x509.X509CertInfo;
+
/**
* This class implements an enrollment default policy
* that populates Authority Key Identifier extension
@@ -161,18 +164,27 @@ 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);
+ String aidString = request.getExtDataInString(
+ IEnrollProfile.REQUEST_AUTHORITY_ID);
+ if (aidString != null)
+ ca = ca.getCA(new AuthorityID(aidString));
+ if (ca == null)
+ 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 1d1d05ed5..696830ead 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/base/PKIService.java b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
index 4ebf075cb..fe77fd567 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/base/PKIService.java
@@ -56,7 +56,10 @@ public class PKIService {
public static List<MediaType> MESSAGE_FORMATS = Arrays.asList(
MediaType.APPLICATION_XML_TYPE,
MediaType.APPLICATION_JSON_TYPE,
- MediaType.APPLICATION_FORM_URLENCODED_TYPE
+ MediaType.APPLICATION_FORM_URLENCODED_TYPE,
+ MediaType.valueOf("application/pkix-cert"),
+ MediaType.valueOf("application/pkcs7-mime"),
+ MediaType.valueOf("application/x-pem-file")
);
public final static int MIN_FILTER_LENGTH = 3;
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java b/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
index c94ee1496..27d8b8262 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
@@ -175,7 +175,7 @@ public class CertRequestDAO extends CMSRequestDAO {
results = processor.processRenewal(data, request);
} else {
EnrollmentProcessor processor = new EnrollmentProcessor("caProfileSubmit", locale);
- results = processor.processEnrollment(data, request);
+ results = processor.processEnrollment(data, request, null);
}
IRequest reqs[] = (IRequest[]) results.get(CAProcessor.ARG_REQUESTS);
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 960f997cd..e5b9a14df 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,8 @@ 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.ca.AuthorityID;
+import com.netscape.certsrv.profile.IEnrollProfile;
import com.netscape.certsrv.profile.IProfile;
import com.netscape.certsrv.profile.IProfileAuthenticator;
import com.netscape.certsrv.profile.IProfileContext;
@@ -98,7 +100,7 @@ public class EnrollmentProcessor extends CertProcessor {
}
CertEnrollmentRequest data = CertEnrollmentRequestFactory.create(cmsReq, profile, locale);
- return processEnrollment(data, cmsReq.getHttpReq());
+ return processEnrollment(data, cmsReq.getHttpReq(), null);
}
/**
@@ -118,8 +120,11 @@ public class EnrollmentProcessor extends CertProcessor {
* @param cmsReq the object holding the request and response information
* @exception EBaseException an error has occurred
*/
- public HashMap<String, Object> processEnrollment(CertEnrollmentRequest data, HttpServletRequest request)
- throws EBaseException {
+ public HashMap<String, Object> processEnrollment(
+ CertEnrollmentRequest data,
+ HttpServletRequest request,
+ AuthorityID aid)
+ throws EBaseException {
try {
if (CMS.debugOn()) {
@@ -146,6 +151,10 @@ public class EnrollmentProcessor extends CertProcessor {
}
IProfileContext ctx = profile.createContext();
+
+ if (aid != null)
+ ctx.set(IEnrollProfile.REQUEST_AUTHORITY_ID, aid.toString());
+
CMS.debug("EnrollmentProcessor: set Inputs into profile Context");
setInputsIntoContext(data, profile, ctx);
diff --git a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
index 2826f477e..8558ec23f 100644
--- a/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
+++ b/base/server/cms/src/com/netscape/cms/servlet/cert/RequestProcessor.java
@@ -36,6 +36,10 @@ import com.netscape.certsrv.base.BadRequestException;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.EPropertyNotFound;
import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.certsrv.ca.AuthorityID;
+import com.netscape.certsrv.ca.CADisabledException;
+import com.netscape.certsrv.ca.CANotFoundException;
+import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.cert.CertReviewResponse;
import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.profile.EDeferException;
@@ -327,6 +331,31 @@ public class RequestProcessor extends CertProcessor {
}
/**
+ * Ensure validity of AuthorityID and that CA exists and is enabled.
+ */
+ private void ensureCAEnabled(String aidString) throws EBaseException {
+ AuthorityID aid = null;
+ try {
+ aid = new AuthorityID(aidString);
+ } catch (IllegalArgumentException e) {
+ // this shouldn't happen because request was already accepted
+ throw new BadRequestDataException("Invalid AuthorityID in request data");
+ }
+ ICertificateAuthority ca = (ICertificateAuthority)
+ CMS.getSubsystem("ca");
+ if (ca == null)
+ // this shouldn't happen
+ throw new CANotFoundException("Could not get host authority"); // shouldn't happen
+ ca = ca.getCA(aid);
+ if (ca == null)
+ // this shouldn't happen because request was already accepted
+ throw new CANotFoundException("Unknown CA: " + aidString);
+ if (!ca.getAuthorityEnabled())
+ // authority was disabled after request was accepted
+ throw new CADisabledException("CA '" + aidString + "' is disabled");
+ }
+
+ /**
* Approve request
* <P>
*
@@ -346,11 +375,16 @@ public class RequestProcessor extends CertProcessor {
* occurred
*/
private void approveRequest(IRequest req, CertReviewResponse data, IProfile profile, Locale locale)
- throws EProfileException {
+ throws EBaseException {
String auditMessage = null;
String auditSubjectID = auditSubjectID();
String auditRequesterID = auditRequesterID(req);
+ // ensure target CA is enabled
+ String aidString = req.getExtDataInString(IEnrollProfile.REQUEST_AUTHORITY_ID);
+ if (aidString != null)
+ ensureCAEnabled(aidString);
+
try {
profile.execute(req);
req.setRequestStatus(RequestStatus.COMPLETE);
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 36b0e4d0d..c0729d881 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() - "