439507 - Possible timing side-channel when comparing MD5-Credentials
+ Using correct digestMismatch logic + Fixing test cases: + No longer reuses / shares directories + Is now Windows build/test compatible + No longer deleteOnExit() the test data (let maven clean and/or test init do that) + Empty directories are now verified + Using server.getURI() instead of URL string manipulation
This commit is contained in:
parent
e39adb337f
commit
c4c8426069
|
@ -160,19 +160,19 @@ public abstract class Credential implements Serializable
|
|||
digest = __md.digest();
|
||||
}
|
||||
if (digest == null || digest.length != _digest.length) return false;
|
||||
boolean match=true;
|
||||
boolean digestMismatch = false;
|
||||
for (int i = 0; i < digest.length; i++)
|
||||
match&=digest[i] != _digest[i];
|
||||
return match;
|
||||
digestMismatch |= (digest[i] != _digest[i]);
|
||||
return !digestMismatch;
|
||||
}
|
||||
else if (credentials instanceof MD5)
|
||||
{
|
||||
MD5 md5 = (MD5) credentials;
|
||||
if (_digest.length != md5._digest.length) return false;
|
||||
boolean match=true;
|
||||
boolean digestMismatch = false;
|
||||
for (int i = 0; i < _digest.length; i++)
|
||||
match&=(_digest[i] != md5._digest[i]);
|
||||
return match;
|
||||
digestMismatch |= (_digest[i] != md5._digest[i]);
|
||||
return !digestMismatch;
|
||||
}
|
||||
else if (credentials instanceof Credential)
|
||||
{
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.sql.Connection;
|
|||
import java.sql.DriverManager;
|
||||
import java.sql.Statement;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.derby.jdbc.EmbeddedDataSource;
|
||||
|
@ -37,9 +36,8 @@ import org.eclipse.jetty.client.api.AuthenticationStore;
|
|||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.util.BasicAuthentication;
|
||||
import org.eclipse.jetty.plus.security.DataSourceLoginService;
|
||||
import org.eclipse.jetty.security.JDBCLoginService;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -58,40 +56,34 @@ public class DataSourceLoginServiceTest
|
|||
private static File _dbRoot;
|
||||
private static HttpClient _client;
|
||||
private static String __realm = "DSRealm";
|
||||
private static String _baseUrl;
|
||||
private static URI _baseUri;
|
||||
private static final int __cacheInterval = 200;
|
||||
private static DatabaseLoginServiceTestServer _testServer;
|
||||
|
||||
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception
|
||||
{
|
||||
_docRoot = new File("target/test-output/docroot/");
|
||||
_docRoot.mkdirs();
|
||||
_docRoot.deleteOnExit();
|
||||
_docRoot = MavenTestingUtils.getTargetTestingDir(DataSourceLoginServiceTest.class.getSimpleName());
|
||||
FS.ensureEmpty(_docRoot);
|
||||
|
||||
File content = new File(_docRoot,"input.txt");
|
||||
FileOutputStream out = new FileOutputStream(content);
|
||||
out.write(_content.getBytes("utf-8"));
|
||||
out.close();
|
||||
|
||||
_dbRoot = new File("target/test-output/derby");
|
||||
_dbRoot = new File(_docRoot, "derby");
|
||||
String dbPath = _dbRoot.getAbsolutePath();
|
||||
System.setProperty("derby.system.home", dbPath);
|
||||
if (_dbRoot.exists())
|
||||
IO.delete(_dbRoot);
|
||||
FS.ensureEmpty(_dbRoot);
|
||||
|
||||
_dbRoot.mkdirs();
|
||||
|
||||
DatabaseLoginServiceTestServer.createDB(dbPath, "src/test/resources/createdb.sql", "jdbc:derby:dstest;create=true");
|
||||
File scriptFile = MavenTestingUtils.getTestResourceFile("createdb.sql");
|
||||
DatabaseLoginServiceTestServer.createDB(dbPath, scriptFile, "jdbc:derby:dstest;create=true");
|
||||
|
||||
_testServer = new DatabaseLoginServiceTestServer();
|
||||
_testServer.setResourceBase(_docRoot.getAbsolutePath());
|
||||
_testServer.setLoginService(configureLoginService());
|
||||
_testServer.start();
|
||||
_baseUrl = _testServer.getBaseUrl();
|
||||
_baseUri = _testServer.getBaseUri();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
@ -141,7 +133,7 @@ public class DataSourceLoginServiceTest
|
|||
{
|
||||
startClient("jetty", "jetty");
|
||||
|
||||
ContentResponse response = _client.GET(_baseUrl + "input.txt");
|
||||
ContentResponse response = _client.GET(_baseUri.resolve("input.txt"));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
assertEquals(_content, response.getContentAsString());
|
||||
|
||||
|
@ -154,7 +146,7 @@ public class DataSourceLoginServiceTest
|
|||
|
||||
startClient("jetty", newpwd);
|
||||
|
||||
response = _client.GET(_baseUrl + "input.txt");
|
||||
response = _client.GET(_baseUri.resolve("input.txt"));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
assertEquals(_content, response.getContentAsString());
|
||||
|
||||
|
@ -185,7 +177,7 @@ public class DataSourceLoginServiceTest
|
|||
executor.setName(executor.getName() + "-client");
|
||||
_client.setExecutor(executor);
|
||||
AuthenticationStore authStore = _client.getAuthenticationStore();
|
||||
authStore.addAuthentication(new BasicAuthentication(URI.create(_baseUrl), __realm, user, pwd));
|
||||
authStore.addAuthentication(new BasicAuthentication(_baseUri, __realm, user, pwd));
|
||||
_client.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.io.FileInputStream;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
|
@ -43,36 +44,37 @@ import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
|||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
|
||||
|
||||
/**
|
||||
* DatabaseLoginServiceTestServer
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class DatabaseLoginServiceTestServer
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(DatabaseLoginServiceTestServer.class);
|
||||
protected Server _server;
|
||||
protected static String _protocol;
|
||||
protected static String _baseUrl;
|
||||
protected static URI _baseUri;
|
||||
protected LoginService _loginService;
|
||||
protected String _resourceBase;
|
||||
protected TestHandler _handler;
|
||||
protected static String _requestContent;
|
||||
|
||||
protected static boolean createDB(String homeDir, String fileName, String dbUrl)
|
||||
protected static boolean createDB(String homeDir, File scriptFile, String dbUrl)
|
||||
{
|
||||
File scriptFile = new File(fileName);
|
||||
try (FileInputStream fileStream = new FileInputStream(scriptFile))
|
||||
{
|
||||
Loader.loadClass(fileStream.getClass(), "org.apache.derby.jdbc.EmbeddedDriver").newInstance();
|
||||
|
@ -85,6 +87,7 @@ public class DatabaseLoginServiceTestServer
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Unable to create EmbeddedDriver",e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -116,12 +119,11 @@ public class DatabaseLoginServiceTestServer
|
|||
baseRequest.setHandled(true);
|
||||
|
||||
File file = new File(_resourcePath, URLDecoder.decode(request.getPathInfo()));
|
||||
file.getParentFile().mkdirs();
|
||||
file.deleteOnExit();
|
||||
FS.ensureDirExists(file.getParentFile());
|
||||
|
||||
out = new FileOutputStream(file);
|
||||
|
||||
response.setStatus(HttpServletResponse.SC_CREATED);
|
||||
response.setStatus(HttpServletResponse.SC_CREATED);
|
||||
}
|
||||
|
||||
if (baseRequest.getMethod().equals("POST"))
|
||||
|
@ -175,8 +177,8 @@ public class DatabaseLoginServiceTestServer
|
|||
{
|
||||
configureServer();
|
||||
_server.start();
|
||||
int port = ((NetworkConnector)_server.getConnectors()[0]).getLocalPort();
|
||||
_baseUrl = _protocol+"://localhost:"+port+ "/";
|
||||
//_server.dumpStdErr();
|
||||
_baseUri = _server.getURI();
|
||||
}
|
||||
|
||||
public void stop() throws Exception
|
||||
|
@ -184,9 +186,9 @@ public class DatabaseLoginServiceTestServer
|
|||
_server.stop();
|
||||
}
|
||||
|
||||
public String getBaseUrl()
|
||||
public URI getBaseUri()
|
||||
{
|
||||
return _baseUrl;
|
||||
return _baseUri;
|
||||
}
|
||||
|
||||
public TestHandler getTestHandler()
|
||||
|
|
|
@ -38,6 +38,8 @@ import org.eclipse.jetty.http.HttpMethod;
|
|||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.security.JDBCLoginService;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -64,39 +66,38 @@ public class JdbcLoginServiceTest
|
|||
private static File _docRoot;
|
||||
private static HttpClient _client;
|
||||
private static String __realm = "JdbcRealm";
|
||||
private static String _baseUrl;
|
||||
private static URI _baseUri;
|
||||
private static DatabaseLoginServiceTestServer _testServer;
|
||||
|
||||
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() throws Exception
|
||||
{
|
||||
_docRoot = new File("target/test-output/docroot/");
|
||||
_docRoot.mkdirs();
|
||||
_docRoot.deleteOnExit();
|
||||
_docRoot = MavenTestingUtils.getTargetTestingDir(JdbcLoginServiceTest.class.getSimpleName());
|
||||
FS.ensureEmpty(_docRoot);
|
||||
|
||||
File content = new File(_docRoot,"input.txt");
|
||||
FileOutputStream out = new FileOutputStream(content);
|
||||
out.write(_content.getBytes("utf-8"));
|
||||
out.close();
|
||||
|
||||
try (FileOutputStream out = new FileOutputStream(content))
|
||||
{
|
||||
out.write(_content.getBytes("utf-8"));
|
||||
}
|
||||
|
||||
File dbRoot = new File("target/test-output/derby");
|
||||
File dbRoot = new File(_docRoot, "derby");
|
||||
String dbPath = dbRoot.getAbsolutePath();
|
||||
System.setProperty("derby.system.home", dbPath);
|
||||
if (dbRoot.exists())
|
||||
IO.delete(dbRoot);
|
||||
FS.ensureEmpty(dbRoot);
|
||||
|
||||
dbRoot.mkdirs();
|
||||
File scriptFile = MavenTestingUtils.getTestResourceFile("createdb.sql");
|
||||
DatabaseLoginServiceTestServer.createDB(dbPath, scriptFile, "jdbc:derby:jdbcrealm;create=true");
|
||||
|
||||
DatabaseLoginServiceTestServer.createDB(dbPath, "src/test/resources/createdb.sql", "jdbc:derby:jdbcrealm;create=true");
|
||||
LoginService loginService = new JDBCLoginService(__realm, "./src/test/resources/jdbcrealm.properties");
|
||||
File jdbcRealmFile = MavenTestingUtils.getTestResourceFile("jdbcrealm.properties");
|
||||
|
||||
LoginService loginService = new JDBCLoginService(__realm, jdbcRealmFile.getAbsolutePath());
|
||||
_testServer = new DatabaseLoginServiceTestServer();
|
||||
_testServer.setResourceBase(_docRoot.getAbsolutePath());
|
||||
_testServer.setLoginService(loginService);
|
||||
_testServer.start();
|
||||
_baseUrl = _testServer.getBaseUrl();
|
||||
_baseUri = _testServer.getBaseUri();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
@ -117,7 +118,7 @@ public class JdbcLoginServiceTest
|
|||
{
|
||||
startClient();
|
||||
|
||||
Request request = _client.newRequest(_baseUrl + "output.txt");
|
||||
Request request = _client.newRequest(_baseUri.resolve("output.txt"));
|
||||
request.method(HttpMethod.PUT);
|
||||
request.content(new BytesContentProvider(_content.getBytes()));
|
||||
ContentResponse response = request.send();
|
||||
|
@ -140,7 +141,7 @@ public class JdbcLoginServiceTest
|
|||
{
|
||||
startClient();
|
||||
|
||||
ContentResponse response = _client.GET(_baseUrl + "input.txt");
|
||||
ContentResponse response = _client.GET(_baseUri.resolve("input.txt"));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
assertEquals(_content, response.getContentAsString());
|
||||
}
|
||||
|
@ -158,7 +159,7 @@ public class JdbcLoginServiceTest
|
|||
{
|
||||
startClient();
|
||||
|
||||
Request request = _client.newRequest(_baseUrl + "input.txt");
|
||||
Request request = _client.newRequest(_baseUri.resolve("input.txt"));
|
||||
request.method(HttpMethod.HEAD);
|
||||
ContentResponse response = request.send();
|
||||
int responseStatus = response.getStatus();
|
||||
|
@ -177,7 +178,7 @@ public class JdbcLoginServiceTest
|
|||
{
|
||||
startClient();
|
||||
|
||||
Request request = _client.newRequest(_baseUrl + "test");
|
||||
Request request = _client.newRequest(_baseUri.resolve("test"));
|
||||
request.method(HttpMethod.POST);
|
||||
request.content(new BytesContentProvider(_content.getBytes()));
|
||||
ContentResponse response = request.send();
|
||||
|
@ -198,7 +199,7 @@ public class JdbcLoginServiceTest
|
|||
executor.setName(executor.getName() + "-client");
|
||||
_client.setExecutor(executor);
|
||||
AuthenticationStore authStore = _client.getAuthenticationStore();
|
||||
authStore.addAuthentication(new BasicAuthentication(URI.create(_baseUrl), __realm, "jetty", "jetty"));
|
||||
authStore.addAuthentication(new BasicAuthentication(_baseUri, __realm, "jetty", "jetty"));
|
||||
_client.start();
|
||||
}
|
||||
|
||||
|
@ -212,17 +213,13 @@ public class JdbcLoginServiceTest
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected HttpClient getClient()
|
||||
{
|
||||
return _client;
|
||||
}
|
||||
|
||||
|
||||
protected String getContent()
|
||||
{
|
||||
return _content;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
#org.eclipse.jetty.LEVEL=DEBUG
|
||||
#org.eclipse.jetty.server.LEVEL=DEBUG
|
Loading…
Reference in New Issue