Merged branch 'jetty-9.3.x' into 'jetty-9.4.x'.

This commit is contained in:
Simone Bordet 2016-11-07 19:26:18 +01:00
commit 7716ada9dd
4 changed files with 89 additions and 96 deletions

View File

@ -1,5 +1,6 @@
# GPG Release Key Fingerprints # GPG Release Key Fingerprints
Jan Bartel AED5 EE6C 45D0 FE8D 5D1B 164F 27DE D4BF 6216 DB Jan Bartel AED5 EE6C 45D0 FE8D 5D1B 164F 27DE D4BF 6216 DB
Simone Bordet 8B09 6546 B1A8 F026 56B1 5D3B 1677 D141 BCF3 58 Simone Bordet 8B09 6546 B1A8 F026 56B1 5D3B 1677 D141 BCF3 58
Joakim Erdfelt BFBB 21C2 46D7 7768 3628 7A48 A04E 0C74 ABB3 5F Joakim Erdfelt <joakim@erdfelt.com> BFBB 21C2 46D7 7768 3628 7A48 A04E 0C74 ABB3 5FEA
Joakim Erdfelt <joakim@apache.org> B59B 67FD 7904 9843 67F9 3180 0818 D9D6 8FB6 7BAC
Jesse McConnell 2A68 4B57 436A 81FA 8706 B53C 61C3 351A 438A 3B7D Jesse McConnell 2A68 4B57 436A 81FA 8706 B53C 61C3 351A 438A 3B7D

View File

@ -99,7 +99,10 @@ public class DigestAuthentication extends AbstractAuthentication
clientQOP = "auth-int"; clientQOP = "auth-int";
} }
return new DigestResult(headerInfo.getHeader(), response.getContent(), getRealm(), user, password, algorithm, nonce, clientQOP, opaque); String realm = getRealm();
if (ANY_REALM.equals(realm))
realm = headerInfo.getRealm();
return new DigestResult(headerInfo.getHeader(), response.getContent(), realm, user, password, algorithm, nonce, clientQOP, opaque);
} }
private Map<String, String> parseParameters(String wwwAuthenticate) private Map<String, String> parseParameters(String wwwAuthenticate)

View File

@ -135,6 +135,14 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
test_Authentication(new DigestAuthentication(uri, realm, "digest", "digest")); test_Authentication(new DigestAuthentication(uri, realm, "digest", "digest"));
} }
@Test
public void test_DigestAnyRealm() throws Exception
{
startDigest(new EmptyServerHandler());
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
test_Authentication(new DigestAuthentication(uri, Authentication.ANY_REALM, "digest", "digest"));
}
private void test_Authentication(Authentication authentication) throws Exception private void test_Authentication(Authentication authentication) throws Exception
{ {
AuthenticationStore authenticationStore = client.getAuthenticationStore(); AuthenticationStore authenticationStore = client.getAuthenticationStore();

View File

@ -23,6 +23,7 @@ import java.nio.charset.StandardCharsets;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.BitSet; import java.util.BitSet;
import java.util.Objects;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
@ -50,8 +51,6 @@ import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential; import org.eclipse.jetty.util.security.Credential;
/** /**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*
* The nonce max age in ms 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". The nonce max count can be set with {@link SecurityHandler#setInitParameter(String, String)} * using the name "maxNonceAge". The nonce max count can be set with {@link SecurityHandler#setInitParameter(String, String)}
* using the name "maxNonceCount". When the age or count is exceeded, the nonce is considered stale. * using the name "maxNonceCount". When the age or count is exceeded, the nonce is considered stale.
@ -59,47 +58,13 @@ import org.eclipse.jetty.util.security.Credential;
public class DigestAuthenticator extends LoginAuthenticator public class DigestAuthenticator extends LoginAuthenticator
{ {
private static final Logger LOG = Log.getLogger(DigestAuthenticator.class); private static final Logger LOG = Log.getLogger(DigestAuthenticator.class);
SecureRandom _random = new SecureRandom();
private final SecureRandom _random = new SecureRandom();
private long _maxNonceAgeMs = 60 * 1000; private long _maxNonceAgeMs = 60 * 1000;
private int _maxNC = 1024; private int _maxNC = 1024;
private ConcurrentMap<String, Nonce> _nonceMap = new ConcurrentHashMap<String, Nonce>(); private ConcurrentMap<String, Nonce> _nonceMap = new ConcurrentHashMap<>();
private Queue<Nonce> _nonceQueue = new ConcurrentLinkedQueue<Nonce>(); private Queue<Nonce> _nonceQueue = new ConcurrentLinkedQueue<>();
private static class Nonce
{
final String _nonce;
final long _ts;
final BitSet _seen;
public Nonce(String nonce, long ts, int size)
{
_nonce=nonce;
_ts=ts;
_seen = new BitSet(size);
}
public boolean seen(int count)
{
synchronized (this)
{
if (count>=_seen.size())
return true;
boolean s=_seen.get(count);
_seen.set(count);
return s;
}
}
}
/* ------------------------------------------------------------ */
public DigestAuthenticator()
{
super();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.authentication.LoginAuthenticator#setConfiguration(org.eclipse.jetty.security.Authenticator.AuthConfiguration)
*/
@Override @Override
public void setConfiguration(AuthConfiguration configuration) public void setConfiguration(AuthConfiguration configuration)
{ {
@ -107,57 +72,44 @@ public class DigestAuthenticator extends LoginAuthenticator
String mna = configuration.getInitParameter("maxNonceAge"); String mna = configuration.getInitParameter("maxNonceAge");
if (mna != null) if (mna != null)
{ setMaxNonceAge(Long.valueOf(mna));
_maxNonceAgeMs=Long.valueOf(mna);
}
String mnc = configuration.getInitParameter("maxNonceCount"); String mnc = configuration.getInitParameter("maxNonceCount");
if (mnc != null) if (mnc != null)
{ setMaxNonceCount(Integer.valueOf(mnc));
_maxNC=Integer.valueOf(mnc);
}
} }
/* ------------------------------------------------------------ */
public int getMaxNonceCount() public int getMaxNonceCount()
{ {
return _maxNC; return _maxNC;
} }
/* ------------------------------------------------------------ */
public void setMaxNonceCount(int maxNC) public void setMaxNonceCount(int maxNC)
{ {
_maxNC = maxNC; _maxNC = maxNC;
} }
/* ------------------------------------------------------------ */
public long getMaxNonceAge() public long getMaxNonceAge()
{ {
return _maxNonceAgeMs; return _maxNonceAgeMs;
} }
/* ------------------------------------------------------------ */ public void setMaxNonceAge(long maxNonceAgeInMillis)
public synchronized void setMaxNonceAge(long maxNonceAgeInMillis)
{ {
_maxNonceAgeMs = maxNonceAgeInMillis; _maxNonceAgeMs = maxNonceAgeInMillis;
} }
/* ------------------------------------------------------------ */
@Override @Override
public String getAuthMethod() public String getAuthMethod()
{ {
return Constraint.__DIGEST_AUTH; return Constraint.__DIGEST_AUTH;
} }
/* ------------------------------------------------------------ */
@Override @Override
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{ {
return true; return true;
} }
/* ------------------------------------------------------------ */
@Override @Override
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
{ {
@ -261,10 +213,17 @@ public class DigestAuthenticator extends LoginAuthenticator
{ {
throw new ServerAuthException(e); throw new ServerAuthException(e);
} }
} }
/* ------------------------------------------------------------ */ @Override
public UserIdentity login(String username, Object credentials, ServletRequest request)
{
Digest digest = (Digest)credentials;
if (!Objects.equals(digest.realm, _loginService.getName()))
return null;
return super.login(username, credentials, request);
}
public String newNonce(Request request) public String newNonce(Request request)
{ {
Nonce nonce; Nonce nonce;
@ -274,7 +233,7 @@ public class DigestAuthenticator extends LoginAuthenticator
byte[] nounce = new byte[24]; byte[] nounce = new byte[24];
_random.nextBytes(nounce); _random.nextBytes(nounce);
nonce = new Nonce(new String(B64Code.encode(nounce)),request.getTimeStamp(),_maxNC); nonce = new Nonce(new String(B64Code.encode(nounce)), request.getTimeStamp(), getMaxNonceCount());
} }
while (_nonceMap.putIfAbsent(nonce._nonce, nonce) != null); while (_nonceMap.putIfAbsent(nonce._nonce, nonce) != null);
_nonceQueue.add(nonce); _nonceQueue.add(nonce);
@ -283,15 +242,14 @@ public class DigestAuthenticator extends LoginAuthenticator
} }
/** /**
* @param nstring nonce to check * @param digest the digest data to check
* @param request * @param request the request object
* @return -1 for a bad nonce, 0 for a stale none, 1 for a good nonce * @return -1 for a bad nonce, 0 for a stale none, 1 for a good nonce
*/ */
/* ------------------------------------------------------------ */
private int checkNonce(Digest digest, Request request) private int checkNonce(Digest digest, Request request)
{ {
// firstly let's expire old nonces // firstly let's expire old nonces
long expired = request.getTimeStamp()-_maxNonceAgeMs; long expired = request.getTimeStamp() - getMaxNonceAge();
Nonce nonce = _nonceQueue.peek(); Nonce nonce = _nonceQueue.peek();
while (nonce != null && nonce._ts < expired) while (nonce != null && nonce._ts < expired)
{ {
@ -323,9 +281,32 @@ public class DigestAuthenticator extends LoginAuthenticator
return -1; return -1;
} }
/* ------------------------------------------------------------ */ private static class Nonce
/* ------------------------------------------------------------ */ {
/* ------------------------------------------------------------ */ final String _nonce;
final long _ts;
final BitSet _seen;
public Nonce(String nonce, long ts, int size)
{
_nonce = nonce;
_ts = ts;
_seen = new BitSet(size);
}
public boolean seen(int count)
{
synchronized (this)
{
if (count >= _seen.size())
return true;
boolean s = _seen.get(count);
_seen.set(count);
return s;
}
}
}
private static class Digest extends Credential private static class Digest extends Credential
{ {
private static final long serialVersionUID = -2484639019549527724L; private static final long serialVersionUID = -2484639019549527724L;