From bcab07ec72fc02753375ae71719553b57c3ef08f Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Wed, 23 Jan 2013 12:10:52 -0600
Subject: [PATCH] Session-based nonces.

Previously nonces were stored in a global map which might not scale
well due to some issues:
1. The map used the nonces as map keys. There were possible nonce
   collisions which required special handling.
2. The collision handling code was not thread safe. There were
   possible race conditions during concurrent modifications.
3. The map was shared and size limited. If there were a lot of
   users using the system, valid nonces could get pruned.
4. The map mapped the nonces to client certificates. This limited
   the possible authentication methods that could be supported.

Now the code has been modified such that each user has a private map
in the user's session to store the nonces. Additional locking has been
implemented to protect against concurrent modifications. The map now
uses the target of the operation as the map key, eliminating possible
collisions and allowing the use of other authentication methods. Since
this is a private map, it's not affected by the number of users using
the system.

Ticket #474
---
 base/ca/src/CMakeLists.txt                         |  10 +-
 .../src/com/netscape/ca/CertificateAuthority.java  |  41 ++++++--
 .../src/com/netscape/certsrv/base/Nonces.java      | 114 ++++++---------------
 .../netscape/certsrv/ca/ICertificateAuthority.java |   6 +-
 .../com/netscape/cms/servlet/base/CMSServlet.java  |   9 +-
 .../netscape/cms/servlet/cert/CertRequestDAO.java  |  25 ++---
 .../servlet/cert/CertReviewResponseFactory.java    |   6 +-
 .../com/netscape/cms/servlet/cert/CertService.java |  22 ++--
 .../com/netscape/cms/servlet/cert/DoRevoke.java    |  41 +++++---
 .../netscape/cms/servlet/cert/ReasonToRevoke.java  |  32 ++++--
 .../cms/servlet/cert/RequestProcessor.java         |  51 ++++-----
 .../cms/servlet/cert/RevocationProcessor.java      |  55 ++++------
 .../cms/servlet/cert/RevocationServlet.java        |  23 +++--
 .../netscape/cms/servlet/processors/Processor.java |  36 +++++--
 .../cms/servlet/profile/ProfileReviewServlet.java  |  17 ++-
 15 files changed, 249 insertions(+), 239 deletions(-)

diff --git a/base/ca/src/CMakeLists.txt b/base/ca/src/CMakeLists.txt
index e5ef9e5303591c6a4ad923d0f51b65f4d0b90c5b..74533814acff2f156b7924543b80652cbb442707 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 f8f3d7a9b2be96935df1b2ca68dce1ddd496ce8d..50ef503b66939e7e40b57f535dc3b7c4da9d3ca2 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 c28a74fae5da0b7f11cea8516dd27eab88f8af97..57ff30d3541a7cccf34763c615755e4da42d4079 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);
-    }
+        System.out.println("Adding 2 more entries.");
+        nonces.put("d", 4l);
+        nonces.put("e", 5l);
 
-    public int size() {
-        return mNonceList.size();
-    }
-
-    public int maxSize() {
-        return mNonceLimit;
-    }
-
-    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 ee7d60c387eb0ebe5e8683c7972a52a63f7f7dc1..21859a0f2e943dd4a8a502b8fe4fdcf16ed78af8 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 72ced2c53309f7530ed7ab8c0fa93a2b279637fa..744a000e3c5665da88e1b773175fe35db47dbc8e 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 4d0fc38b22011e2dec8cce4fac262d7eacc9e0da..d4785e9572515b0ddc2d06cb7ce841e488561862 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 97611eb94b22a53d951d049caddf7d4d28bc42c7..a7d76a4693d878e119bef14fd2f31247482a653c 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 e049710cb6e4d194d2cab1917f2258d8c37ebb35..69856751d0c8ea50152f659e88556576159038a3 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 5d33bf2bcf5b32598086d1867e84f59dcfc1ce31..272034fc2977230e7e8fad740ec8356dfcbb3260 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);
 
-        if (mAuthority instanceof ICertificateAuthority) {
-            processor.setAuthority((ICertificateAuthority)mAuthority);
-        }
-
+        Hashtable<BigInteger, Long> nonceMap = new Hashtable<BigInteger, Long>();
         X509Certificate clientCert = getSSLClientCertificate(req);
-        String requestedNonce = req.getParameter("nonce");
-        Long nonce = requestedNonce == null ? null : new Long(requestedNonce.trim());
-        processor.validateNonce(clientCert, nonce);
+
+        if (mAuthority instanceof ICertificateAuthority) {
+            processor.setAuthority(certAuthority);
+
+            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 5b9cd774189aaf287e65f34f12f98a1d0aede3fc..75e732676c5d0a8d2e1ffe02751cd082e35f1190 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 508cd72c19f82661e2552c28ce380c536c7b11ce..b5063c24358a6d20669eb8af2c8e1d8e8e8d0de4 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 34131488749534b5597fb79acd2fac2a6ff7d2d5..e555d1ac65608bfd2ad0d86bfab704bc1c813553 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) {
-                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;
-                }
-            }
+        if (clientCert == null) {
+            return false;
+        }
 
-            if (nonce != null) {
-                X509Certificate storedCert = nonces.getCertificate(nonce);
-                if (storedCert == null) {
-                    CMS.debug("RevocationProcessor:  Unknown nonce");
+        try {
+            X509Certificate certChain[] = new X509Certificate[1];
+            certChain[0] = clientCert;
 
-                } else if (clientCert != null && storedCert.equals(clientCert)) {
-                    nonceVerified = true;
-                    nonces.removeNonce(nonce);
-                }
-            } else {
-                CMS.debug("RevocationProcessor:  Missing nonce");
-            }
+            IUser user = ul.locateUser(new Certificates(certChain));
+            return ug.isMemberOf(user, "Subsystem Group");
 
-            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 4c4f7e9e0cb71477517aae49c868bd6bcbc00d0b..d136c5ff9e68553e5047414a44b01342b248847f 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 423d1bed539e2447769f9acfa3a3aef8c093e4eb..42e1bca75c5a9f303ebb0deb85144670c823d8e5 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 61a04a630b2fae0d05288cf49143005ba40fb543..5680f862727735a89b8fb61a286e9a84eb8ef58c 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-revoke");
+            nonces.put(req.getRequestId().toBigInteger(), n);
+            args.set(ARG_REQUEST_NONCE, Long.toString(n));
         }
 
         args.set(ARG_REQUEST_ID, req.getRequestId().toString());
-- 
1.7.12.1

