Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Bartel2011-10-04 02:45:15 -0400
committerJan Bartel2011-10-04 02:45:15 -0400
commit32dbb1bddb9acd51af9054d5dbacc6f67c277fc8 (patch)
tree34a8e84701811bd2a5a2038872e9f838f730a327 /jetty-security/src/main/java
parent246fb51cfcb33fa5190559ac5404df5acdba5f26 (diff)
parentb67d307ff3a1e32ea78ea802b9502910a4d448fc (diff)
downloadorg.eclipse.jetty.project-32dbb1bddb9acd51af9054d5dbacc6f67c277fc8.tar.gz
org.eclipse.jetty.project-32dbb1bddb9acd51af9054d5dbacc6f67c277fc8.tar.xz
org.eclipse.jetty.project-32dbb1bddb9acd51af9054d5dbacc6f67c277fc8.zip
Merge remote-tracking branch 'origin/master' into jetty-8
Conflicts: VERSION.txt example-jetty-embedded/pom.xml jetty-aggregate/jetty-all-server/pom.xml jetty-aggregate/jetty-all/pom.xml jetty-aggregate/jetty-client/pom.xml jetty-aggregate/jetty-plus/pom.xml jetty-aggregate/jetty-server/pom.xml jetty-aggregate/jetty-servlet/pom.xml jetty-aggregate/jetty-webapp/pom.xml jetty-aggregate/pom.xml jetty-ajp/pom.xml jetty-annotations/pom.xml jetty-client/pom.xml jetty-continuation/pom.xml jetty-deploy/pom.xml jetty-deploy/src/main/config/etc/jetty-deploy.xml jetty-distribution/pom.xml jetty-http/pom.xml jetty-io/pom.xml jetty-jaspi/pom.xml jetty-jmx/pom.xml jetty-jndi/pom.xml jetty-jsp-2.1/pom.xml jetty-monitor/pom.xml jetty-nested/pom.xml jetty-nosql/pom.xml jetty-osgi/jetty-osgi-boot-jsp/pom.xml jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java jetty-osgi/jetty-osgi-boot-logback/pom.xml jetty-osgi/jetty-osgi-boot-warurl/pom.xml jetty-osgi/jetty-osgi-boot/pom.xml jetty-osgi/jetty-osgi-equinoxtools/pom.xml jetty-osgi/jetty-osgi-httpservice/pom.xml jetty-osgi/jetty-osgi-servletbridge/pom.xml jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/FrameworkLauncherExtended.java jetty-osgi/jetty-osgi-servletbridge/src/main/webapp/WEB-INF/web.xml jetty-osgi/pom.xml jetty-osgi/test-jetty-osgi/pom.xml jetty-overlay-deployer/pom.xml jetty-plus/pom.xml jetty-policy/pom.xml jetty-rewrite/pom.xml jetty-security/pom.xml jetty-server/pom.xml jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java jetty-servlet/pom.xml jetty-servlets/pom.xml jetty-start/pom.xml jetty-util/pom.xml jetty-webapp/pom.xml jetty-websocket/pom.xml jetty-xml/pom.xml pom.xml test-continuation-jetty6/pom.xml test-continuation/pom.xml test-jetty-nested/pom.xml test-jetty-servlet/pom.xml test-jetty-webapp/pom.xml tests/pom.xml tests/test-integration/pom.xml tests/test-loginservice/pom.xml tests/test-sessions/pom.xml tests/test-sessions/test-hash-sessions/pom.xml tests/test-sessions/test-jdbc-sessions/pom.xml tests/test-sessions/test-sessions-common/pom.xml tests/test-webapps/pom.xml tests/test-webapps/test-webapp-rfc2616/pom.xml
Diffstat (limited to 'jetty-security/src/main/java')
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java3
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java157
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java2
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java46
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java32
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java166
6 files changed, 189 insertions, 217 deletions
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java
index 2b2b746276..472da9c665 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultIdentityService.java
@@ -17,6 +17,9 @@ import java.security.Principal;
import javax.security.auth.Subject;
+import org.eclipse.jetty.http.security.Credential;
+import org.eclipse.jetty.security.MappedLoginService.KnownUser;
+import org.eclipse.jetty.security.MappedLoginService.RolePrincipal;
import org.eclipse.jetty.server.UserIdentity;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
index 5e5a844586..12b51f5150 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/HashLoginService.java
@@ -13,21 +13,12 @@
package org.eclipse.jetty.security;
-import java.io.File;
-import java.io.FilenameFilter;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
import org.eclipse.jetty.http.security.Credential;
+import org.eclipse.jetty.security.PropertyUserStore.UserListener;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.Scanner;
-import org.eclipse.jetty.util.Scanner.BulkListener;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
@@ -36,27 +27,24 @@ import org.eclipse.jetty.util.resource.Resource;
/**
* Properties User Realm.
*
- * An implementation of UserRealm that stores users and roles in-memory in
- * HashMaps.
+ * An implementation of UserRealm that stores users and roles in-memory in HashMaps.
* <P>
- * Typically these maps are populated by calling the load() method or passing a
- * properties resource to the constructor. The format of the properties file is:
+ * Typically these maps are populated by calling the load() method or passing a properties resource to the constructor. The format of the properties file is:
*
* <PRE>
* username: password [,rolename ...]
* </PRE>
*
- * Passwords may be clear text, obfuscated or checksummed. The class
- * com.eclipse.Util.Password should be used to generate obfuscated passwords or
- * password checksums.
+ * Passwords may be clear text, obfuscated or checksummed. The class com.eclipse.Util.Password should be used to generate obfuscated passwords or password
+ * checksums.
*
- * If DIGEST Authentication is used, the password must be in a recoverable
- * format, either plain text or OBF:.
+ * If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:.
*/
-public class HashLoginService extends MappedLoginService
+public class HashLoginService extends MappedLoginService implements UserListener
{
private static final Logger LOG = Log.getLogger(HashLoginService.class);
+ private PropertyUserStore _propertyUserStore;
private String _config;
private Resource _configResource;
private Scanner _scanner;
@@ -72,14 +60,14 @@ public class HashLoginService extends MappedLoginService
{
setName(name);
}
-
+
/* ------------------------------------------------------------ */
public HashLoginService(String name, String config)
{
setName(name);
setConfig(config);
}
-
+
/* ------------------------------------------------------------ */
public String getConfig()
{
@@ -89,7 +77,7 @@ public class HashLoginService extends MappedLoginService
/* ------------------------------------------------------------ */
public void getConfig(String config)
{
- _config=config;
+ _config = config;
}
/* ------------------------------------------------------------ */
@@ -100,11 +88,10 @@ public class HashLoginService extends MappedLoginService
/* ------------------------------------------------------------ */
/**
- * Load realm users from properties file. The property file maps usernames
- * to password specs followed by an optional comma separated list of role
- * names.
+ * Load realm users from properties file. The property file maps usernames to password specs followed by an optional comma separated list of role names.
*
- * @param config Filename or url of user properties file.
+ * @param config
+ * Filename or url of user properties file.
*/
public void setConfig(String config)
{
@@ -129,52 +116,14 @@ public class HashLoginService extends MappedLoginService
{
return null;
}
-
+
/* ------------------------------------------------------------ */
@Override
public void loadUsers() throws IOException
{
- if (_config==null)
- return;
- _configResource = Resource.newResource(_config);
-
- if (LOG.isDebugEnabled()) LOG.debug("Load " + this + " from " + _config);
- Properties properties = new Properties();
- properties.load(_configResource.getInputStream());
- Set<String> known = new HashSet<String>();
-
- for (Map.Entry<Object, Object> entry : properties.entrySet())
- {
- String username = ((String) entry.getKey()).trim();
- String credentials = ((String) entry.getValue()).trim();
- String roles = null;
- int c = credentials.indexOf(',');
- if (c > 0)
- {
- roles = credentials.substring(c + 1).trim();
- credentials = credentials.substring(0, c).trim();
- }
-
- if (username != null && username.length() > 0 && credentials != null && credentials.length() > 0)
- {
- String[] roleArray = IdentityService.NO_ROLES;
- if (roles != null && roles.length() > 0)
- roleArray = roles.split(",");
- known.add(username);
- putUser(username,Credential.getCredential(credentials),roleArray);
- }
- }
-
- Iterator<String> users = _users.keySet().iterator();
- while(users.hasNext())
- {
- String user=users.next();
- if (!known.contains(user))
- users.remove();
- }
+ // TODO: Consider refactoring MappedLoginService to not have to override with unused methods
}
-
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
@@ -183,54 +132,17 @@ public class HashLoginService extends MappedLoginService
{
super.doStart();
- if (getRefreshInterval() > 0)
+ if (_propertyUserStore == null)
{
- _scanner = new Scanner();
- _scanner.setScanInterval(getRefreshInterval());
- List<File> dirList = new ArrayList<File>(1);
- dirList.add(_configResource.getFile());
- _scanner.setScanDirs(dirList);
- _scanner.setFilenameFilter(new FilenameFilter()
- {
- public boolean accept(File dir, String name)
- {
- File f = new File(dir, name);
- try
- {
- if (f.compareTo(_configResource.getFile()) == 0) return true;
- }
- catch (IOException e)
- {
- return false;
- }
-
- return false;
- }
-
- });
- _scanner.addListener(new BulkListener()
+ if(LOG.isDebugEnabled())
{
- public void filesChanged(List<String> filenames) throws Exception
- {
- if (filenames == null) return;
- if (filenames.isEmpty()) return;
- if (filenames.size() == 1)
- {
- Resource r = Resource.newResource(filenames.get(0));
- if (r.getFile().equals(_configResource.getFile()))
- loadUsers();
- }
- }
-
- public String toString()
- {
- return "HashLoginService$Scanner";
- }
-
- });
- _scanner.setReportExistingFilesOnStartup(false);
- _scanner.setRecursive(false);
- _scanner.start();
+ LOG.debug("doStart: Starting new PropertyUserStore. PropertiesFile: " + _config + " refreshInterval: " + _refreshInterval);
+ }
+ _propertyUserStore = new PropertyUserStore();
+ _propertyUserStore.setRefreshInterval(_refreshInterval);
+ _propertyUserStore.setConfig(_config);
+ _propertyUserStore.registerUserListener(this);
+ _propertyUserStore.start();
}
}
@@ -241,9 +153,24 @@ public class HashLoginService extends MappedLoginService
protected void doStop() throws Exception
{
super.doStop();
- if (_scanner != null) _scanner.stop();
+ if (_scanner != null)
+ _scanner.stop();
_scanner = null;
}
+
+ /* ------------------------------------------------------------ */
+ public void update(String userName, Credential credential, String[] roleArray)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("update: " + userName + " Roles: " + roleArray.length);
+ putUser(userName,credential,roleArray);
+ }
-
+ /* ------------------------------------------------------------ */
+ public void remove(String userName)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("remove: " + userName);
+ removeUser(userName);
+ }
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java
index e05a000b2e..216ae818d9 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java
@@ -14,9 +14,9 @@
package org.eclipse.jetty.security;
import java.security.Principal;
-
import javax.security.auth.Subject;
+import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
index 5e46316510..b7e64ac123 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
@@ -3,7 +3,9 @@ package org.eclipse.jetty.security;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.security.Principal;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -11,7 +13,12 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import javax.security.auth.Subject;
+
import org.eclipse.jetty.http.security.Credential;
+import org.eclipse.jetty.security.MappedLoginService.KnownUser;
+import org.eclipse.jetty.security.MappedLoginService.RolePrincipal;
+import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.Scanner.BulkListener;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
@@ -42,8 +49,10 @@ public class PropertyUserStore extends AbstractLifeCycle
private Scanner _scanner;
private int _refreshInterval = 0;// default is not to reload
+ private IdentityService _identityService = new DefaultIdentityService();
private boolean _firstLoad = true; // true if first load, false from that point on
private final List<String> _knownUsers = new ArrayList<String>();
+ private final Map<String, UserIdentity> _knownUserIdentities = new HashMap<String, UserIdentity>();
private List<UserListener> _listeners;
/* ------------------------------------------------------------ */
@@ -57,6 +66,12 @@ public class PropertyUserStore extends AbstractLifeCycle
{
_config = config;
}
+
+ /* ------------------------------------------------------------ */
+ public UserIdentity getUserIdentity(String userName)
+ {
+ return _knownUserIdentities.get(userName);
+ }
/* ------------------------------------------------------------ */
/**
@@ -119,9 +134,29 @@ public class PropertyUserStore extends AbstractLifeCycle
{
String[] roleArray = IdentityService.NO_ROLES;
if (roles != null && roles.length() > 0)
+ {
roleArray = roles.split(",");
+ }
known.add(username);
- notifyUpdate(username,Credential.getCredential(credentials),roleArray);
+ Credential credential = Credential.getCredential(credentials);
+
+ Principal userPrincipal = new KnownUser(username,credential);
+ Subject subject = new Subject();
+ subject.getPrincipals().add(userPrincipal);
+ subject.getPrivateCredentials().add(credential);
+
+ if (roles != null)
+ {
+ for (String role : roleArray)
+ {
+ subject.getPrincipals().add(new RolePrincipal(role));
+ }
+ }
+
+ subject.setReadOnly();
+
+ _knownUserIdentities.put(username,_identityService.newUserIdentity(subject,userPrincipal,roleArray));
+ notifyUpdate(username,credential,roleArray);
}
}
@@ -138,6 +173,7 @@ public class PropertyUserStore extends AbstractLifeCycle
String user = users.next();
if (!known.contains(user))
{
+ _knownUserIdentities.remove(user);
notifyRemove(user);
}
}
@@ -201,15 +237,17 @@ public class PropertyUserStore extends AbstractLifeCycle
_scanner.addListener(new BulkListener()
{
- public void filesChanged(List filenames) throws Exception
+ public void filesChanged(List<String> filenames) throws Exception
{
if (filenames == null)
return;
if (filenames.isEmpty())
return;
- if (filenames.size() == 1 && filenames.get(0).equals(getConfigResource().getFile().getAbsolutePath()))
+ if (filenames.size() == 1)
{
- loadUsers();
+ Resource r = Resource.newResource(filenames.get(0));
+ if (r.getFile().equals(_configResource.getFile()))
+ loadUsers();
}
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java
index e680644609..372f9b63ea 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java
@@ -65,20 +65,28 @@ public class BasicAuthenticator extends LoginAuthenticator
return _deferred;
if (credentials != null)
- {
- credentials = credentials.substring(credentials.indexOf(' ')+1);
- credentials = B64Code.decode(credentials,StringUtil.__ISO_8859_1);
- int i = credentials.indexOf(':');
- if (i>0)
+ {
+ int space=credentials.indexOf(' ');
+ if (space>0)
{
- String username = credentials.substring(0,i);
- String password = credentials.substring(i+1);
-
- UserIdentity user = _loginService.login(username,password);
- if (user!=null)
+ String method=credentials.substring(0,space);
+ if ("basic".equalsIgnoreCase(method))
{
- renewSessionOnAuthentication(request,response);
- return new UserAuthentication(getAuthMethod(),user);
+ credentials = credentials.substring(space+1);
+ credentials = B64Code.decode(credentials,StringUtil.__ISO_8859_1);
+ int i = credentials.indexOf(':');
+ if (i>0)
+ {
+ String username = credentials.substring(0,i);
+ String password = credentials.substring(i+1);
+
+ UserIdentity user = _loginService.login(username,password);
+ if (user!=null)
+ {
+ renewSessionOnAuthentication(request,response);
+ return new UserAuthentication(getAuthMethod(),user);
+ }
+ }
}
}
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java
index 7fa563a850..5a2ecf412e 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java
@@ -15,6 +15,12 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException;
import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@@ -42,17 +48,29 @@ import org.eclipse.jetty.util.log.Logger;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*
- * The nonce max age can be set with the {@link SecurityHandler#setInitParameter(String, String)}
+ * The nonce max age in ms can be set with the {@link SecurityHandler#setInitParameter(String, String)}
* using the name "maxNonceAge"
*/
public class DigestAuthenticator extends LoginAuthenticator
{
private static final Logger LOG = Log.getLogger(DigestAuthenticator.class);
+ SecureRandom _random = new SecureRandom();
+ private long _maxNonceAgeMs = 60*1000;
+ private ConcurrentMap<String, Nonce> _nonceCount = new ConcurrentHashMap<String, Nonce>();
+ private Queue<Nonce> _nonceQueue = new ConcurrentLinkedQueue<Nonce>();
+ private static class Nonce
+ {
+ final String _nonce;
+ final long _ts;
+ AtomicInteger _nc=new AtomicInteger();
+ public Nonce(String nonce, long ts)
+ {
+ _nonce=nonce;
+ _ts=ts;
+ }
+ }
- protected long _maxNonceAge = 0;
- protected long _nonceSecret = this.hashCode() ^ System.currentTimeMillis();
- protected boolean _useStale = false;
-
+ /* ------------------------------------------------------------ */
public DigestAuthenticator()
{
super();
@@ -69,19 +87,22 @@ public class DigestAuthenticator extends LoginAuthenticator
String mna=configuration.getInitParameter("maxNonceAge");
if (mna!=null)
- _maxNonceAge=Long.valueOf(mna);
+ _maxNonceAgeMs=Long.valueOf(mna);
}
+ /* ------------------------------------------------------------ */
public String getAuthMethod()
{
return Constraint.__DIGEST_AUTH;
}
-
+
+ /* ------------------------------------------------------------ */
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;
}
+ /* ------------------------------------------------------------ */
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
{
if (!mandatory)
@@ -144,7 +165,7 @@ public class DigestAuthenticator extends LoginAuthenticator
}
}
- int n = checkNonce(digest.nonce, (Request)request);
+ int n = checkNonce(digest,(Request)request);
if (n > 0)
{
@@ -170,8 +191,8 @@ public class DigestAuthenticator extends LoginAuthenticator
+ domain
+ "\", nonce=\""
+ newNonce((Request)request)
- + "\", algorithm=MD5, qop=\"auth\""
- + (_useStale ? (" stale=" + stale) : ""));
+ + "\", algorithm=MD5, qop=\"auth\","
+ + " stale=" + stale);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.SEND_CONTINUE;
@@ -186,87 +207,59 @@ public class DigestAuthenticator extends LoginAuthenticator
}
+ /* ------------------------------------------------------------ */
public String newNonce(Request request)
{
- long ts=request.getTimeStamp();
- long sk = _nonceSecret;
-
- byte[] nounce = new byte[24];
- for (int i = 0; i < 8; i++)
- {
- nounce[i] = (byte) (ts & 0xff);
- ts = ts >> 8;
- nounce[8 + i] = (byte) (sk & 0xff);
- sk = sk >> 8;
- }
-
- byte[] hash = null;
- try
- {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.reset();
- md.update(nounce, 0, 16);
- hash = md.digest();
- }
- catch (Exception e)
+ Nonce nonce;
+
+ do
{
- LOG.warn(e);
- }
+ byte[] nounce = new byte[24];
+ _random.nextBytes(nounce);
- for (int i = 0; i < hash.length; i++)
- {
- nounce[8 + i] = hash[i];
- if (i == 23) break;
+ nonce = new Nonce(new String(B64Code.encode(nounce)),request.getTimeStamp());
}
-
- return new String(B64Code.encode(nounce));
+ while (_nonceCount.putIfAbsent(nonce._nonce,nonce)!=null);
+ _nonceQueue.add(nonce);
+
+ return nonce._nonce;
}
/**
- * @param nonce nonce to check
+ * @param nstring nonce to check
* @param request
* @return -1 for a bad nonce, 0 for a stale none, 1 for a good nonce
*/
/* ------------------------------------------------------------ */
- private int checkNonce(String nonce, Request request)
+ private int checkNonce(Digest digest, Request request)
{
+ // firstly let's expire old nonces
+ long expired = request.getTimeStamp()-_maxNonceAgeMs;
+
+ Nonce nonce=_nonceQueue.peek();
+ while (nonce!=null && nonce._ts<expired)
+ {
+ _nonceQueue.remove();
+ _nonceCount.remove(nonce._nonce);
+ nonce=_nonceQueue.peek();
+ }
+
+
try
{
- byte[] n = B64Code.decode(nonce.toCharArray());
- if (n.length != 24) return -1;
-
- long ts = 0;
- long sk = _nonceSecret;
- byte[] n2 = new byte[16];
- System.arraycopy(n, 0, n2, 0, 8);
- for (int i = 0; i < 8; i++)
- {
- n2[8 + i] = (byte) (sk & 0xff);
- sk = sk >> 8;
- ts = (ts << 8) + (0xff & (long) n[7 - i]);
- }
-
- long age = request.getTimeStamp() - ts;
- if (LOG.isDebugEnabled()) LOG.debug("age=" + age);
-
- byte[] hash = null;
- try
- {
- MessageDigest md = MessageDigest.getInstance("MD5");
- md.reset();
- md.update(n2, 0, 16);
- hash = md.digest();
- }
- catch (Exception e)
- {
- LOG.warn(e);
- }
-
- for (int i = 0; i < 16; i++)
- if (n[i + 8] != hash[i]) return -1;
-
- if (_maxNonceAge > 0 && (age < 0 || age > _maxNonceAge)) return 0; // stale
-
+ nonce = _nonceCount.get(digest.nonce);
+ if (nonce==null)
+ return 0;
+
+ long count = Long.parseLong(digest.nc,16);
+ if (count>Integer.MAX_VALUE)
+ return 0;
+ int old=nonce._nc.get();
+ while (!nonce._nc.compareAndSet(old,(int)count))
+ old=nonce._nc.get();
+ if (count<=old)
+ return -1;
+
return 1;
}
catch (Exception e)
@@ -276,18 +269,21 @@ public class DigestAuthenticator extends LoginAuthenticator
return -1;
}
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
private static class Digest extends Credential
{
private static final long serialVersionUID = -2484639019549527724L;
- String method = null;
- String username = null;
- String realm = null;
- String nonce = null;
- String nc = null;
- String cnonce = null;
- String qop = null;
- String uri = null;
- String response = null;
+ final String method;
+ String username = "";
+ String realm = "";
+ String nonce = "";
+ String nc = "";
+ String cnonce = "";
+ String qop = "";
+ String uri = "";
+ String response = "";
/* ------------------------------------------------------------ */
Digest(String m)

Back to the top