diff options
author | Endi Sukma Dewata <edewata@redhat.com> | 2013-01-23 12:10:52 -0600 |
---|---|---|
committer | Endi Sukma Dewata <edewata@redhat.com> | 2013-02-03 00:53:18 -0500 |
commit | 18e9c016c02d0909d6267c517be0675784a3db3d (patch) | |
tree | ae79ff683cb7e7b2c53b2b3fcef1740810c3d89d /base/common/src/com/netscape/certsrv | |
parent | 6c2bc7b0f502531e86b8a7af789c7d81b3bbff09 (diff) | |
download | pki-18e9c016c02d0909d6267c517be0675784a3db3d.tar.gz pki-18e9c016c02d0909d6267c517be0675784a3db3d.tar.xz pki-18e9c016c02d0909d6267c517be0675784a3db3d.zip |
Session-based nonces.
Previously nonces were stored in a global map which might not scale
well due to some issues:
1. The map uses 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 maps the nonces to client certificates. This limits
the possible authentication methods that can 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
Diffstat (limited to 'base/common/src/com/netscape/certsrv')
-rw-r--r-- | base/common/src/com/netscape/certsrv/base/Nonces.java | 114 | ||||
-rw-r--r-- | base/common/src/com/netscape/certsrv/ca/ICertificateAuthority.java | 6 |
2 files changed, 37 insertions, 83 deletions
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. |