summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/ca/src/CMakeLists.txt10
-rw-r--r--base/ca/src/com/netscape/ca/CertificateAuthority.java41
-rw-r--r--base/common/src/com/netscape/certsrv/base/Nonces.java114
-rw-r--r--base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java6
-rw-r--r--base/common/src/com/netscape/cms/servlet/base/CMSServlet.java9
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/CertRequestDAO.java25
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java6
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/CertService.java22
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java39
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java32
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java51
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java55
-rw-r--r--base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java23
-rw-r--r--base/common/src/com/netscape/cms/servlet/processors/Processor.java36
-rw-r--r--base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java17
15 files changed, 248 insertions, 238 deletions
diff --git a/base/ca/src/CMakeLists.txt b/base/ca/src/CMakeLists.txt
index e5ef9e530..74533814a 100644
--- a/base/ca/src/CMakeLists.txt
+++ b/base/ca/src/CMakeLists.txt
@@ -31,6 +31,14 @@ find_file(JAXRS_API_JAR
${RESTEASY_LIB}
)
+find_file(SERVLET_JAR
+ NAMES
+ servlet.jar
+ PATHS
+ ${JAVA_LIB_INSTALL_DIR}
+ /usr/share/java
+)
+
# build pki-ca
javac(pki-ca-classes
SOURCES
@@ -39,7 +47,7 @@ javac(pki-ca-classes
${PKI_CERTSRV_JAR} ${PKI_CMS_JAR} ${PKI_CMSCORE_JAR}
${PKI_CMSUTIL_JAR} ${PKI_NSUTIL_JAR}
${LDAPJDK_JAR} ${JAXRS_API_JAR}
- ${JSS_JAR} ${COMMONS_CODEC_JAR} ${SYMKEY_JAR}
+ ${JSS_JAR} ${COMMONS_CODEC_JAR} ${SYMKEY_JAR} ${SERVLET_JAR}
OUTPUT_DIR
${CMAKE_BINARY_DIR}/classes
DEPENDS
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthority.java b/base/ca/src/com/netscape/ca/CertificateAuthority.java
index f8f3d7a9b..50ef503b6 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthority.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthority.java
@@ -29,11 +29,16 @@ import java.security.PublicKey;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
+import java.util.Map;
import java.util.Vector;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
import netscape.security.util.DerOutputStream;
import netscape.security.util.DerValue;
import netscape.security.x509.AlgorithmId;
@@ -65,6 +70,7 @@ import com.netscape.certsrv.base.EPropertyNotFound;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.ISubsystem;
import com.netscape.certsrv.base.Nonces;
+import com.netscape.certsrv.base.PKIException;
import com.netscape.certsrv.ca.ECAException;
import com.netscape.certsrv.ca.ICRLIssuingPoint;
import com.netscape.certsrv.ca.ICertificateAuthority;
@@ -219,7 +225,6 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
private boolean mUseNonces = true;
private int mMaxNonces = 100;
- private Nonces mNonces = null;
/**
* Constructs a CA subsystem.
@@ -279,8 +284,34 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
return mUseNonces;
}
- public Nonces getNonces() {
- return mNonces;
+ public Map<Object, Long> getNonces(HttpServletRequest request, String name) {
+
+ // Create a new session or use an existing one.
+ HttpSession session = request.getSession(true);
+ if (session == null) {
+ throw new PKIException("Unable to create session.");
+ }
+
+ // Lock the session to prevent concurrent access.
+ // http://yet-another-dev.blogspot.com/2009/08/synchronizing-httpsession.html
+
+ Object lock = request.getSession().getId().intern();
+ synchronized (lock) {
+
+ // Find the existing storage in the session.
+ @SuppressWarnings("unchecked")
+ Map<Object, Long> nonces = (Map<Object, Long>)session.getAttribute("nonces-"+name);
+
+ if (nonces == null) {
+ // If not present, create a new storage.
+ nonces = Collections.synchronizedMap(new Nonces(mMaxNonces));
+
+ // Put the storage in the session.
+ session.setAttribute("nonces-"+name, nonces);
+ }
+
+ return nonces;
+ }
}
/**
@@ -319,10 +350,6 @@ public class CertificateAuthority implements ICertificateAuthority, ICertAuthori
mUseNonces = mConfig.getBoolean("enableNonces", true);
mMaxNonces = mConfig.getInteger("maxNumberOfNonces", 100);
- if (mUseNonces) {
- mNonces = new Nonces(mMaxNonces);
- CMS.debug("CertificateAuthority init: Nonces enabled. (" + mNonces.size() + ")");
- }
// init request queue and related modules.
CMS.debug("CertificateAuthority init: initRequestQueue");
diff --git a/base/common/src/com/netscape/certsrv/base/Nonces.java b/base/common/src/com/netscape/certsrv/base/Nonces.java
index c28a74fae..57ff30d35 100644
--- a/base/common/src/com/netscape/certsrv/base/Nonces.java
+++ b/base/common/src/com/netscape/certsrv/base/Nonces.java
@@ -17,107 +17,59 @@
// --- END COPYRIGHT BLOCK ---
package com.netscape.certsrv.base;
-import java.security.cert.X509Certificate;
-import java.util.Hashtable;
-import java.util.Vector;
+import java.util.LinkedHashMap;
+import java.util.Map;
/**
- * This class manages nonces sometimes used to control request state flow.
- * <P>
+ * This class provides a limited storage for nonces. Usually
+ * nonces are added and removed immediately. In case some of
+ * the nonces are abandoned, the oldest nonce will be removed
+ * if the storage size grows exceeding the limit.
*
* @version $Revision$, $Date$
*/
-public class Nonces {
+public class Nonces extends LinkedHashMap<Object,Long> {
- private Hashtable<Long, X509Certificate> mNonces = new Hashtable<Long, X509Certificate>();
- private Vector<Long> mNonceList = new Vector<Long>();
- private int mNonceLimit;
+ private static final long serialVersionUID = 7953840029228765259L;
+
+ private int limit;
- /**
- * Constructs nonces.
- */
public Nonces() {
this(100);
}
public Nonces(int limit) {
- mNonceLimit = limit;
+ this.limit = limit;
}
- public long addNonce(long nonce, X509Certificate cert) {
- long i;
- long k = 0;
- long n = nonce;
- long m = (mNonceLimit / 2) + 1;
-
- for (i = 0; i < m; i++) {
- k = n + i;
- // avoid collisions
- if (!mNonceList.contains(k)) {
- break;
- }
- k = n - i;
- // avoid collisions
- if (!mNonceList.contains(k)) {
- break;
- }
- }
- if (i < m) {
- mNonceList.add(k);
- mNonces.put(k, cert);
- if (mNonceList.size() > mNonceLimit) {
- n = mNonceList.firstElement().longValue();
- mNonceList.remove(0);
- mNonces.remove(n);
- }
- } else {
- // failed to resolved collision
- k = -nonce;
- }
- return k;
+ /**
+ * Override removeEldestEntry() to remove eldest entry
+ * if the size exceeds the limit.
+ */
+ protected boolean removeEldestEntry(Map.Entry<Object,Long> eldest) {
+ return size() > limit;
}
- public X509Certificate getCertificate(long nonce) {
- X509Certificate cert = mNonces.get(nonce);
- return cert;
- }
+ public static void main(String[] args) {
+ Nonces nonces = new Nonces(3);
- public X509Certificate getCertificate(int index) {
- X509Certificate cert = null;
- if (index >= 0 && index < mNonceList.size()) {
- long nonce = mNonceList.elementAt(index).longValue();
- cert = mNonces.get(nonce);
- }
- return cert;
- }
+ System.out.println("Adding 3 entries.");
+ nonces.put("a", 1l);
+ nonces.put("b", 2l);
+ nonces.put("c", 3l);
- public long getNonce(int index) {
- long nonce = 0;
- if (index >= 0 && index < mNonceList.size()) {
- nonce = mNonceList.elementAt(index).longValue();
+ System.out.println("Nonces:");
+ for (Object id : nonces.keySet()) {
+ System.out.println(" - "+id+": "+nonces.get(id));
}
- return nonce;
- }
-
- public void removeNonce(long nonce) {
- mNonceList.remove(nonce);
- mNonces.remove(nonce);
- }
-
- public int size() {
- return mNonceList.size();
- }
- public int maxSize() {
- return mNonceLimit;
- }
+ System.out.println("Adding 2 more entries.");
+ nonces.put("d", 4l);
+ nonces.put("e", 5l);
- public void clear() {
- mNonceList.clear();
- mNonces.clear();
- }
-
- public boolean isInSync() {
- return (mNonceList.size() == mNonces.size());
+ System.out.println("Nonces:");
+ for (Object id : nonces.keySet()) {
+ System.out.println(" - "+id+": "+nonces.get(id));
+ }
}
}
diff --git a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
index ee7d60c38..21859a0f2 100644
--- a/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
+++ b/base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java
@@ -18,6 +18,9 @@
package com.netscape.certsrv.ca;
import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
import netscape.security.x509.CertificateChain;
import netscape.security.x509.CertificateVersion;
@@ -31,7 +34,6 @@ import org.mozilla.jss.crypto.SignatureAlgorithm;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.ISubsystem;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
import com.netscape.certsrv.dbs.crldb.ICRLRepository;
import com.netscape.certsrv.dbs.replicadb.IReplicaIDRepository;
@@ -132,7 +134,7 @@ public interface ICertificateAuthority extends ISubsystem {
public boolean noncesEnabled();
- public Nonces getNonces();
+ public Map<Object, Long> getNonces(HttpServletRequest request, String name);
/**
* Retrieves the publishing processor of this certificate authority.
diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java
index 72ced2c53..744a000e3 100644
--- a/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java
+++ b/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java
@@ -226,6 +226,7 @@ public abstract class CMSServlet extends HttpServlet {
// the authority, RA, CA, KRA this servlet is serving.
protected IAuthority mAuthority = null;
+ protected ICertificateAuthority certAuthority;
protected IRequestQueue mRequestQueue = null;
// system logger.
@@ -301,9 +302,11 @@ public abstract class CMSServlet extends HttpServlet {
authority = sc.getInitParameter(PROP_AUTHORITYID);
}
- if (authority != null)
- mAuthority = (IAuthority)
- CMS.getSubsystem(authority);
+ if (authority != null) {
+ mAuthority = (IAuthority) CMS.getSubsystem(authority);
+ if (mAuthority instanceof ICertificateAuthority)
+ certAuthority = (ICertificateAuthority) mAuthority;
+ }
if (mAuthority != null)
mRequestQueue = mAuthority.getRequestQueue();
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertRequestDAO.java b/base/common/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
index 4d0fc38b2..d4785e957 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertRequestDAO.java
@@ -21,6 +21,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
import java.util.Random;
import javax.servlet.ServletException;
@@ -29,7 +30,6 @@ import javax.ws.rs.core.UriInfo;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.cert.CertEnrollmentRequest;
import com.netscape.certsrv.cert.CertRequestInfo;
@@ -54,7 +54,6 @@ public class CertRequestDAO extends CMSRequestDAO {
private IRequestQueue queue;
private ICertificateAuthority ca;
IProfileSubsystem ps;
- private Nonces nonces = null;
private Random random = null;
public static final String ATTR_SERIALNO = "serialNumber";
@@ -65,7 +64,6 @@ public class CertRequestDAO extends CMSRequestDAO {
queue = ca.getRequestQueue();
if (ca.noncesEnabled()) {
random = new Random();
- nonces = ca.getNonces();
}
ps = (IProfileSubsystem) CMS.getSubsystem(IProfileSubsystem.ID);
}
@@ -141,20 +139,19 @@ public class CertRequestDAO extends CMSRequestDAO {
String profileId = request.getExtDataInString("profileId");
IProfile profile = ps.getProfile(profileId);
CertReviewResponse info = CertReviewResponseFactory.create(request, profile, uriInfo, locale);
- if (ca.noncesEnabled()) {
- addNonce(info, servletRequest);
- }
- return info;
- }
- private void addNonce(CertReviewResponse info, HttpServletRequest servletRequest) throws EBaseException {
- if (nonces != null) {
+ if (ca.noncesEnabled()) {
+ // generate nonce
long n = random.nextLong();
- long m = nonces.addNonce(n, Processor.getSSLClientCertificate(servletRequest));
- if ((n + m) != 0) {
- info.setNonce(Long.toString(m));
- }
+
+ // store nonce in session
+ Map<Object, Long> nonces = ca.getNonces(servletRequest, "cert-request");
+ nonces.put(info.getRequestId().toBigInteger(), n);
+
+ // return nonce to client
+ info.setNonce(Long.toString(n));
}
+ return info;
}
/**
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java b/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
index 97611eb94..a7d76a469 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertReviewResponseFactory.java
@@ -26,7 +26,6 @@ import javax.ws.rs.core.UriInfo;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IArgBlock;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.cert.CertReviewResponse;
import com.netscape.certsrv.profile.EProfileException;
import com.netscape.certsrv.profile.IPolicyDefault;
@@ -128,7 +127,8 @@ public class CertReviewResponseFactory {
return ret;
}
- public static CertReviewResponse create(CMSRequest cmsReq, IProfile profile, Nonces nonces, Locale locale)
+ public static CertReviewResponse create(
+ CMSRequest cmsReq, IProfile profile, boolean noncesEnabled, Locale locale)
throws EPropertyException, EProfileException {
HttpServletRequest req = cmsReq.getHttpReq();
IRequest ireq = cmsReq.getIRequest();
@@ -139,7 +139,7 @@ public class CertReviewResponseFactory {
ret.setRequestNotes(req.getParameter("requestNotes"));
ret.setRequestId(ireq.getRequestId());
- if (nonces != null) {
+ if (noncesEnabled) {
ret.setNonce(req.getParameter(Processor.ARG_REQUEST_NONCE));
}
diff --git a/base/common/src/com/netscape/cms/servlet/cert/CertService.java b/base/common/src/com/netscape/cms/servlet/cert/CertService.java
index e049710cb..69856751d 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/CertService.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/CertService.java
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
+import java.util.Map;
import java.util.Random;
import netscape.security.pkcs.ContentInfo;
@@ -44,7 +45,6 @@ import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.base.BadRequestException;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.ICertPrettyPrint;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.base.PKIException;
import com.netscape.certsrv.base.UnauthorizedException;
import com.netscape.certsrv.ca.ICertificateAuthority;
@@ -80,7 +80,6 @@ public class CertService extends PKIService implements CertResource {
ICertificateAuthority authority;
ICertificateRepository repo;
Random random;
- Nonces nonces;
public final static int DEFAULT_SIZE = 20;
@@ -88,7 +87,6 @@ public class CertService extends PKIService implements CertResource {
authority = (ICertificateAuthority) CMS.getSubsystem("ca");
if (authority.noncesEnabled()) {
random = new Random();
- nonces = authority.getNonces();
}
repo = authority.getCertificateRepository();
}
@@ -195,7 +193,11 @@ public class CertService extends PKIService implements CertResource {
}
}
- processor.validateNonce(clientCert, request.getNonce());
+ if (authority.noncesEnabled() &&
+ !processor.isMemberOfSubsystemGroup(clientCert)) {
+ processor.validateNonce(servletRequest, "cert-revoke", id.toBigInteger(), request.getNonce());
+
+ }
// Find target cert record if different from client cert.
ICertRecord targetRecord = id.equals(clientSerialNumber) ? clientRecord : processor.getCertificateRecord(id);
@@ -470,12 +472,14 @@ public class CertService extends PKIService implements CertResource {
certData.setStatus(record.getStatus());
- if (generateNonce && nonces != null) {
+ if (authority.noncesEnabled() && generateNonce) {
+ // generate nonce
long n = random.nextLong();
- long m = nonces.addNonce(n, Processor.getSSLClientCertificate(servletRequest));
- if (n + m != 0) {
- certData.setNonce(m);
- }
+ // store nonce in session
+ Map<Object, Long> nonces = authority.getNonces(servletRequest, "cert-revoke");
+ nonces.put(certId.toBigInteger(), n);
+ // return nonce to client
+ certData.setNonce(n);
}
URI uri = uriInfo.getBaseUriBuilder().path(CertResource.class).path("{id}").build(certId.toHexString());
diff --git a/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java b/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java
index 5d33bf2bc..272034fc2 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
+import java.util.Hashtable;
import java.util.Locale;
import java.util.Vector;
@@ -49,7 +50,6 @@ import com.netscape.certsrv.authorization.EAuthzAccessDenied;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.ForbiddenException;
import com.netscape.certsrv.base.IArgBlock;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.base.PKIException;
import com.netscape.certsrv.ca.ICRLIssuingPoint;
import com.netscape.certsrv.ca.ICertificateAuthority;
@@ -87,7 +87,6 @@ public class DoRevoke extends CMSServlet {
private ICertificateRepository mCertDB = null;
private String mFormPath = null;
private IPublisherProcessor mPublisherProcessor = null;
- private Nonces mNonces = null;
private int mTimeLimits = 30; /* in seconds */
private IUGSubsystem mUG = null;
private ICertUserLocator mUL = null;
@@ -111,9 +110,6 @@ public class DoRevoke extends CMSServlet {
if (mAuthority instanceof ICertificateAuthority) {
mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository();
- if (((ICertificateAuthority) mAuthority).noncesEnabled()) {
- mNonces = ((ICertificateAuthority) mAuthority).getNonces();
- }
}
if (mAuthority instanceof ICertAuthority) {
mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor();
@@ -401,14 +397,27 @@ public class DoRevoke extends CMSServlet {
processor.setInvalidityDate(invalidityDate);
processor.setComments(comments);
+ Hashtable<BigInteger, Long> nonceMap = new Hashtable<BigInteger, Long>();
+ X509Certificate clientCert = getSSLClientCertificate(req);
+
if (mAuthority instanceof ICertificateAuthority) {
- processor.setAuthority((ICertificateAuthority)mAuthority);
- }
+ processor.setAuthority(certAuthority);
- X509Certificate clientCert = getSSLClientCertificate(req);
- String requestedNonce = req.getParameter("nonce");
- Long nonce = requestedNonce == null ? null : new Long(requestedNonce.trim());
- processor.validateNonce(clientCert, nonce);
+ if (certAuthority.noncesEnabled()) {
+ String nonces = req.getParameter("nonce");
+ if (nonces == null) {
+ throw new ForbiddenException("Missing nonce.");
+ }
+
+ // parse serial numbers and nonces
+ for (String s : nonces.split(",")) {
+ String[] elements = s.split(":");
+ BigInteger serialNumber = new BigInteger(elements[0].trim());
+ Long nonce = new Long(elements[1].trim());
+ nonceMap.put(serialNumber, nonce);
+ }
+ }
+ }
try {
processor.createCRLExtension();
@@ -437,6 +446,14 @@ public class DoRevoke extends CMSServlet {
rarg.addStringValue("serialNumber", targetCert.getSerialNumber().toString(16));
try {
+ if (mAuthority instanceof ICertificateAuthority &&
+ certAuthority.noncesEnabled() &&
+ !processor.isMemberOfSubsystemGroup(clientCert)) {
+ // validate nonce for each certificate
+ Long nonce = nonceMap.get(targetRecord.getSerialNumber());
+ processor.validateNonce(req, "cert-revoke", targetRecord.getSerialNumber(), nonce);
+ }
+
processor.validateCertificateToRevoke(eeSubjectDN, targetRecord, false);
processor.addCertificateToRevoke(targetCert);
rarg.addStringValue("error", null);
diff --git a/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java b/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
index 5b9cd7741..75e732676 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java
@@ -18,8 +18,10 @@
package com.netscape.cms.servlet.cert;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Locale;
+import java.util.Map;
import java.util.Random;
import javax.servlet.ServletConfig;
@@ -30,13 +32,14 @@ import javax.servlet.http.HttpServletResponse;
import netscape.security.x509.X509CertImpl;
+import org.apache.commons.lang.StringUtils;
+
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.IAuthToken;
import com.netscape.certsrv.authorization.AuthzToken;
import com.netscape.certsrv.authorization.EAuthzAccessDenied;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IArgBlock;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.certdb.ICertRecord;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
@@ -65,7 +68,6 @@ public class ReasonToRevoke extends CMSServlet {
private String mFormPath = null;
private ICertificateAuthority mCA = null;
private Random mRandom = null;
- private Nonces mNonces = null;
private int mTimeLimits = 30; /* in seconds */
public ReasonToRevoke() {
@@ -88,7 +90,6 @@ public class ReasonToRevoke extends CMSServlet {
if (mCA != null && mCA.noncesEnabled()) {
mRandom = new Random();
- mNonces = mCA.getNonces();
}
mTemplates.remove(CMSRequest.SUCCESS);
@@ -222,14 +223,6 @@ public class ReasonToRevoke extends CMSServlet {
header.addStringValue("revokeAll", revokeAll);
header.addIntegerValue("totalRecordCount", totalRecordCount);
- if (mNonces != null) {
- long n = mRandom.nextLong();
- long m = mNonces.addNonce(n, getSSLClientCertificate(req));
- if ((n + m) != 0) {
- header.addStringValue("nonce", Long.toString(m));
- }
- }
-
try {
if (mCA != null) {
X509CertImpl caCert = mCA.getSigningUnit().getCertImpl();
@@ -248,6 +241,7 @@ public class ReasonToRevoke extends CMSServlet {
Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll,
totalRecordCount, mTimeLimits);
+ ArrayList<String> noncesList = new ArrayList<String>();
int count = 0;
while (e != null && e.hasMoreElements()) {
@@ -258,6 +252,17 @@ public class ReasonToRevoke extends CMSServlet {
X509CertImpl xcert = rec.getCertificate();
if (xcert != null)
+
+ if (mCA != null && mCA.noncesEnabled()) {
+ // generate nonce
+ long n = mRandom.nextLong();
+ // store nonce in session
+ Map<Object, Long> nonces = mCA.getNonces(req, "cert-revoke");
+ nonces.put(xcert.getSerialNumber(), n);
+ // store serial number and nonce
+ noncesList.add(xcert.getSerialNumber()+":"+n);
+ }
+
if (!(rec.getStatus().equals(ICertRecord.STATUS_REVOKED))) {
count++;
IArgBlock rarg = CMS.createArgBlock();
@@ -278,6 +283,11 @@ public class ReasonToRevoke extends CMSServlet {
header.addIntegerValue("verifiedRecordCount", count);
+ if (mCA != null && mCA.noncesEnabled()) {
+ // return serial numbers and nonces to client
+ header.addStringValue("nonce", StringUtils.join(noncesList.toArray(), ","));
+ }
+
} catch (EBaseException e) {
log(ILogger.LL_FAILURE, "Error " + e);
throw e;
diff --git a/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java
index 508cd72c1..b5063c243 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/RequestProcessor.java
@@ -17,7 +17,6 @@
// --- END COPYRIGHT BLOCK ---
package com.netscape.cms.servlet.cert;
-import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@@ -33,6 +32,7 @@ import com.netscape.certsrv.authentication.IAuthToken;
import com.netscape.certsrv.authorization.AuthzToken;
import com.netscape.certsrv.authorization.EAuthzException;
import com.netscape.certsrv.base.BadRequestDataException;
+import com.netscape.certsrv.base.BadRequestException;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.EPropertyNotFound;
import com.netscape.certsrv.base.IConfigStore;
@@ -71,7 +71,8 @@ public class RequestProcessor extends CertProcessor {
String profileId = ireq.getExtDataInString("profileId");
IProfile profile = ps.getProfile(profileId);
- CertReviewResponse data = CertReviewResponseFactory.create(cmsReq, profile, nonces, locale);
+ CertReviewResponse data = CertReviewResponseFactory.create(
+ cmsReq, profile, authority.noncesEnabled(), locale);
processRequest(req, data, request, op);
return data;
@@ -99,41 +100,27 @@ public class RequestProcessor extends CertProcessor {
throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR"));
}
- if (nonces != null) {
+ if (authority.noncesEnabled()) {
+ Object id = data.getRequestId().toBigInteger();
+
String requestNonce = data.getNonce();
- boolean nonceVerified = false;
- if (requestNonce != null) {
- long nonce = 0L;
- try {
- nonce = Long.parseLong(requestNonce.trim());
- } catch (NumberFormatException e) {
- }
- X509Certificate cert1 = nonces.getCertificate(nonce);
- X509Certificate cert2 = getSSLClientCertificate(request);
- if (cert1 == null) {
- CMS.debug("CertRequestExecutor: Unknown nonce");
- } else if (cert1 != null && cert2 != null && cert1.equals(cert2)) {
- nonceVerified = true;
- nonces.removeNonce(nonce);
- }
- } else {
- CMS.debug("CertRequestExecutor: Missing nonce");
- }
- CMS.debug("CertRequestExecutor: nonceVerified=" + nonceVerified);
- if (!nonceVerified) {
- CMS.debug("nonce not verified");
- throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR"));
+ if (requestNonce == null) {
+ CMS.debug("RequestProcessor: Missing nonce");
+ throw new BadRequestException("Missing nonce.");
}
+
+ Long nonce = new Long(requestNonce.trim());
+ validateNonce(request, "cert-request", id, nonce);
}
- CMS.debug("CertRequestExecutor: processRequest: start serving");
+ CMS.debug("RequestProcessor: processRequest: start serving");
RequestId requestId = data.getRequestId();
if (requestId == null || requestId.equals("")) {
CMS.debug(CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND"));
throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_REQUEST_ID_NOT_FOUND"));
}
- CMS.debug("CertRequestExecutor: requestId=" + requestId);
+ CMS.debug("RequestProcessor: requestId=" + requestId);
// check if the request is in one of the terminal states
if (!req.getRequestStatus().equals(RequestStatus.PENDING)) {
@@ -147,10 +134,10 @@ public class RequestProcessor extends CertProcessor {
String profileId = req.getExtDataInString("profileId");
if (profileId == null || profileId.equals("")) {
- CMS.debug("CertRequestExecutor: Profile Id not found in request");
+ CMS.debug("RequestProcessor: Profile Id not found in request");
throw new EBaseException(CMS.getUserMessage(locale, "CMS_PROFILE_ID_NOT_FOUND"));
}
- CMS.debug("CertRequestExecutor: profileId=" + profileId);
+ CMS.debug("RequestProcessor: profileId=" + profileId);
IProfile profile = ps.getProfile(profileId);
if (profile == null) {
@@ -158,7 +145,7 @@ public class RequestProcessor extends CertProcessor {
throw new BadRequestDataException(CMS.getUserMessage(locale, "CMS_PROFILE_NOT_FOUND", profileId));
}
if (!ps.isProfileEnable(profileId)) {
- CMS.debug("CertRequestExecutor: Profile " + profileId + " not enabled");
+ CMS.debug("RequestProcessor: Profile " + profileId + " not enabled");
throw new BadRequestDataException("Profile " + profileId + " not enabled");
}
@@ -168,7 +155,7 @@ public class RequestProcessor extends CertProcessor {
// assigned owner
if (owner != null && owner.length() > 0) {
if (!grantPermission(req, authToken)) {
- CMS.debug("CertRequestExecutor: Permission not granted to assign request.");
+ CMS.debug("RequestProcessor: Permission not granted to assign request.");
throw new EAuthzException(CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION"));
}
}
@@ -197,7 +184,7 @@ public class RequestProcessor extends CertProcessor {
req.setRequestOwner("");
}
} else {
- CMS.debug("CertRequestExecutor: Permission not granted to approve/reject/cancel/update/validate/unassign request.");
+ CMS.debug("RequestProcessor: Permission not granted to approve/reject/cancel/update/validate/unassign request.");
throw new EAuthzException(CMS.getUserMessage(locale, "CMS_PROFILE_DENY_OPERATION"));
}
}
diff --git a/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java b/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java
index 341314887..e555d1ac6 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/RevocationProcessor.java
@@ -26,7 +26,12 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import com.netscape.certsrv.authorization.EAuthzException;
import netscape.security.x509.CRLExtensions;
import netscape.security.x509.CRLReasonExtension;
import netscape.security.x509.InvalidityDateExtension;
@@ -39,6 +44,7 @@ import com.netscape.certsrv.base.BadRequestException;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.EPropertyNotFound;
import com.netscape.certsrv.base.ForbiddenException;
+import com.netscape.certsrv.base.PKIException;
import com.netscape.certsrv.base.UnauthorizedException;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.certdb.CertId;
@@ -188,47 +194,24 @@ public class RevocationProcessor extends CertProcessor {
return request;
}
- public void validateNonce(X509Certificate clientCert, Long nonce) {
+ public boolean isMemberOfSubsystemGroup(X509Certificate clientCert) {
- if (nonces != null) {
- boolean nonceVerified = false;
- boolean skipNonceVerification = false;
+ if (clientCert == null) {
+ return false;
+ }
- if (clientCert != null) {
- X509Certificate certChain[] = new X509Certificate[1];
- certChain[0] = clientCert;
- IUser user = null;
- try {
- user = ul.locateUser(new Certificates(certChain));
- } catch (Exception e) {
- CMS.debug("RevocationProcessor: Failed to map certificate '" +
- clientCert.getSubjectDN().getName() + "' to user.");
- }
- if (ug.isMemberOf(user, "Subsystem Group")) {
- skipNonceVerification = true;
- }
- }
+ try {
+ X509Certificate certChain[] = new X509Certificate[1];
+ certChain[0] = clientCert;
- if (nonce != null) {
- X509Certificate storedCert = nonces.getCertificate(nonce);
- if (storedCert == null) {
- CMS.debug("RevocationProcessor: Unknown nonce");
+ IUser user = ul.locateUser(new Certificates(certChain));
+ return ug.isMemberOf(user, "Subsystem Group");
- } else if (clientCert != null && storedCert.equals(clientCert)) {
- nonceVerified = true;
- nonces.removeNonce(nonce);
- }
- } else {
- CMS.debug("RevocationProcessor: Missing nonce");
- }
-
- CMS.debug("RevocationProcessor: nonceVerified=" + nonceVerified);
- CMS.debug("RevocationProcessor: skipNonceVerification=" + skipNonceVerification);
- if ((!nonceVerified) && (!skipNonceVerification)) {
- throw new ForbiddenException("Invalid nonce.");
- }
+ } catch (Exception e) {
+ CMS.debug("RevocationProcessor: Failed to map certificate '" +
+ clientCert.getSubjectDN().getName() + "' to user.");
+ return false;
}
-
}
public void validateCertificateToRevoke(String subjectDN, ICertRecord targetRecord, boolean revokingCACert) {
diff --git a/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java b/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java
index 4c4f7e9e0..d136c5ff9 100644
--- a/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java
+++ b/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java
@@ -23,6 +23,7 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale;
+import java.util.Map;
import java.util.Random;
import javax.servlet.ServletConfig;
@@ -42,7 +43,6 @@ import com.netscape.certsrv.authorization.AuthzToken;
import com.netscape.certsrv.authorization.EAuthzAccessDenied;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.IArgBlock;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.certdb.ICertRecord;
import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
@@ -82,7 +82,6 @@ public class RevocationServlet extends CMSServlet {
private boolean mRevokeByDN = true;
private Random mRandom = null;
- private Nonces mNonces = null;
public RevocationServlet() {
super();
@@ -109,7 +108,6 @@ public class RevocationServlet extends CMSServlet {
if (mAuthority instanceof ICertificateAuthority) {
if (((ICertificateAuthority) mAuthority).noncesEnabled()) {
- mNonces = ((ICertificateAuthority) mAuthority).getNonces();
mRandom = new Random();
}
}
@@ -207,18 +205,21 @@ public class RevocationServlet extends CMSServlet {
// header.addLongValue("validNotBefore", old_cert.getNotBefore().getTime()/1000);
// header.addLongValue("validNotAfter", old_cert.getNotAfter().getTime()/1000);
- if (mNonces != null) {
- long n = mRandom.nextLong();
- long m = mNonces.addNonce(n, old_cert);
- if ((n + m) != 0) {
- header.addStringValue("nonce", Long.toString(m));
- }
- }
-
boolean noInfo = false;
X509CertImpl[] certsToRevoke = null;
if (mAuthority instanceof ICertificateAuthority) {
+
+ if (certAuthority.noncesEnabled()) {
+ // generate nonce
+ long n = mRandom.nextLong();
+ // store nonce in session
+ Map<Object, Long> nonces = certAuthority.getNonces(cmsReq.getHttpReq(), "cert-revoke");
+ nonces.put(old_serial_no, n);
+ // return serial number and nonce to client
+ header.addStringValue("nonce", old_serial_no+":"+n);
+ }
+
certsToRevoke = ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificates(
old_cert.getSubjectDN().toString(),
ICertificateRepository.ALL_UNREVOKED_CERTS);
diff --git a/base/common/src/com/netscape/cms/servlet/processors/Processor.java b/base/common/src/com/netscape/cms/servlet/processors/Processor.java
index 423d1bed5..42e1bca75 100644
--- a/base/common/src/com/netscape/cms/servlet/processors/Processor.java
+++ b/base/common/src/com/netscape/cms/servlet/processors/Processor.java
@@ -28,6 +28,7 @@ import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Locale;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
@@ -39,13 +40,14 @@ import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.AuthToken;
import com.netscape.certsrv.authentication.IAuthToken;
import com.netscape.certsrv.authorization.AuthzToken;
+import com.netscape.certsrv.authorization.EAuthzException;
import com.netscape.certsrv.authorization.IAuthzSubsystem;
+import com.netscape.certsrv.base.BadRequestException;
import com.netscape.certsrv.base.EBaseException;
import com.netscape.certsrv.base.EPropertyNotFound;
import com.netscape.certsrv.base.IArgBlock;
import com.netscape.certsrv.base.IConfigStore;
import com.netscape.certsrv.base.MetaInfo;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.base.SessionContext;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.dbs.certdb.ICertRecord;
@@ -138,7 +140,6 @@ public class Processor {
protected String authzResourceName;
protected String authMgr;
protected String getClientCert = "false";
- protected Nonces nonces;
protected Locale locale;
// subsystems
@@ -179,10 +180,6 @@ public class Processor {
throw new EBaseException("CertProcessor: authority is null");
}
- if (authority.noncesEnabled()) {
- nonces = authority.getNonces();
- }
-
queue = authority.getRequestQueue();
if (queue == null) {
throw new EBaseException("CertProcessor: cannot get request queue");
@@ -1237,4 +1234,31 @@ public class Processor {
return ILogger.SIGNED_AUDIT_EMPTY_VALUE;
}
}
+
+ public void validateNonce(
+ HttpServletRequest servletRequest,
+ String name,
+ Object id,
+ Long nonce) throws EBaseException {
+
+ if (nonce == null) {
+ throw new BadRequestException("Missing nonce.");
+ }
+
+ Map<Object, Long> nonces = authority.getNonces(servletRequest, name);
+
+ Long storedNonce = nonces.get(id);
+ if (storedNonce == null) {
+ throw new BadRequestException("Nonce for "+name+" "+id+" does not exist.");
+ }
+
+ if (!nonce.equals(storedNonce)) {
+ CMS.debug("Processor: Invalid nonce");
+ throw new EAuthzException(CMS.getUserMessage(locale, "CMS_AUTHORIZATION_ERROR"));
+ }
+
+ nonces.remove(id);
+
+ CMS.debug("Processor: Nonce verified");
+ }
}
diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java
index 61a04a630..2b3ef83bb 100644
--- a/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java
+++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java
@@ -19,6 +19,7 @@ package com.netscape.cms.servlet.profile;
import java.util.Enumeration;
import java.util.Locale;
+import java.util.Map;
import java.util.Random;
import javax.servlet.ServletConfig;
@@ -29,11 +30,9 @@ import javax.servlet.http.HttpServletResponse;
import com.netscape.certsrv.apps.CMS;
import com.netscape.certsrv.authentication.IAuthToken;
-import com.netscape.certsrv.authority.IAuthority;
import com.netscape.certsrv.authorization.AuthzToken;
import com.netscape.certsrv.authorization.EAuthzAccessDenied;
import com.netscape.certsrv.base.EBaseException;
-import com.netscape.certsrv.base.Nonces;
import com.netscape.certsrv.ca.ICertificateAuthority;
import com.netscape.certsrv.logging.ILogger;
import com.netscape.certsrv.profile.EProfileException;
@@ -68,8 +67,8 @@ public class ProfileReviewServlet extends ProfileServlet {
private static final String PROP_AUTHORITY_ID = "authorityId";
private String mAuthorityId = null;
+ ICertificateAuthority authority = null;
private Random mRandom = null;
- private Nonces mNonces = null;
public ProfileReviewServlet() {
}
@@ -84,12 +83,10 @@ public class ProfileReviewServlet extends ProfileServlet {
super.init(sc);
mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID);
- ICertificateAuthority authority = null;
if (mAuthorityId != null)
authority = (ICertificateAuthority) CMS.getSubsystem(mAuthorityId);
if (authority != null && authority.noncesEnabled()) {
- mNonces = authority.getNonces();
mRandom = new Random();
}
}
@@ -168,7 +165,6 @@ public class ProfileReviewServlet extends ProfileServlet {
}
// retrieve request
- IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId);
if (authority == null) {
CMS.debug("ProfileReviewServlet: Authority " + mAuthorityId +
@@ -253,12 +249,11 @@ public class ProfileReviewServlet extends ProfileServlet {
}
}
- if (mNonces != null) {
+ if (authority != null && authority.noncesEnabled()) {
long n = mRandom.nextLong();
- long m = mNonces.addNonce(n, getSSLClientCertificate(request));
- if ((n + m) != 0) {
- args.set(ARG_REQUEST_NONCE, Long.toString(m));
- }
+ Map<Object, Long> nonces = authority.getNonces(request, "cert-request");
+ nonces.put(req.getRequestId().toBigInteger(), n);
+ args.set(ARG_REQUEST_NONCE, Long.toString(n));
}
args.set(ARG_REQUEST_ID, req.getRequestId().toString());