JETTY-1192 Fixed Digested POST

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1383 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-03-16 12:41:11 +00:00
parent fa37afd7fe
commit 0207f90d5b
2 changed files with 341 additions and 0 deletions

View File

@ -0,0 +1,329 @@
package org.eclipse.jetty.test;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.MessageDigest;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.security.Password;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.DefaultIdentityService;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.authentication.DigestAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import junit.framework.TestCase;
public class DigestPostTest extends TestCase
{
private static final String NC = "00000001";
public final static String __message =
"0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 \n"+
"9876543210 9876543210 9876543210 9876543210 9876543210 9876543210 9876543210 9876543210 \n"+
"1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 1234567890 \n"+
"0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 0987654321 \n"+
"abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz \n"+
"ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ ABCDEFGHIJKLMNOPQRSTUVWXYZ \n"+
"Now is the time for all good men to come to the aid of the party.\n"+
"How now brown cow.\n"+
"The quick brown fox jumped over the lazy dog.\n";
public volatile static String _received = null;
private Server _server;
public void setUp()
{
try
{
_server = new Server();
_server.setConnectors(new Connector[]
{ new SelectChannelConnector() });
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SECURITY);
context.setContextPath("/test");
context.addServlet(PostServlet.class,"/");
HashLoginService realm = new HashLoginService("test");
realm.putUser("testuser",new Password("password"),new String[]{"test"});
_server.addBean(realm);
ConstraintSecurityHandler security=(ConstraintSecurityHandler)context.getSecurityHandler();
security.setAuthenticator(new DigestAuthenticator());
security.setLoginService(realm);
Constraint constraint = new Constraint("SecureTest","test");
constraint.setAuthenticate(true);
ConstraintMapping mapping = new ConstraintMapping();
mapping.setConstraint(constraint);
mapping.setPathSpec("/*");
security.setConstraintMappings(new ConstraintMapping[]{mapping});
HandlerCollection handlers = new HandlerCollection();
handlers.setHandlers(new Handler[]
{ context, new DefaultHandler() });
_server.setHandler(handlers);
_server.start();
}
catch (final Exception e)
{
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception
{
_server.stop();
}
public void testServerDirectlyHTTP10() throws Exception
{
Socket socket = new Socket("127.0.0.1",_server.getConnectors()[0].getLocalPort());
byte[] bytes = __message.getBytes("UTF-8");
_received=null;
socket.getOutputStream().write(
("POST /test/ HTTP/1.0\r\n"+
"Host: 127.0.0.1:"+_server.getConnectors()[0].getLocalPort()+"\r\n"+
"Content-Length: "+bytes.length+"\r\n"+
"\r\n").getBytes("UTF-8"));
socket.getOutputStream().write(bytes);
socket.getOutputStream().flush();
String result = IO.toString(socket.getInputStream());
assertTrue(result.startsWith("HTTP/1.1 401 Unauthorized"));
assertEquals(null,_received);
int n=result.indexOf("nonce=");
String nonce=result.substring(n+7,result.indexOf('"',n+7));
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b= md.digest(String.valueOf(System.currentTimeMillis()).getBytes(org.eclipse.jetty.util.StringUtil.__ISO_8859_1));
String cnonce=encode(b);
String digest="Digest username=\"testuser\" realm=\"test\" nonce=\""+nonce+"\" uri=\"/test/\" algorithm=MD5 response=\""+
newResponse("POST","/test/",cnonce,"testuser","test","password",nonce,"auth")+
"\" qop=auth nc="+NC+" cnonce=\""+cnonce+"\"";
socket = new Socket("127.0.0.1",_server.getConnectors()[0].getLocalPort());
_received=null;
socket.getOutputStream().write(
("POST /test/ HTTP/1.0\r\n"+
"Host: 127.0.0.1:"+_server.getConnectors()[0].getLocalPort()+"\r\n"+
"Content-Length: "+bytes.length+"\r\n"+
"Authorization: "+digest+"\r\n"+
"\r\n").getBytes("UTF-8"));
socket.getOutputStream().write(bytes);
socket.getOutputStream().flush();
result = IO.toString(socket.getInputStream());
assertTrue(result.startsWith("HTTP/1.1 200 OK"));
assertEquals(__message,_received);
}
public void testServerDirectlyHTTP11() throws Exception
{
Socket socket = new Socket("127.0.0.1",_server.getConnectors()[0].getLocalPort());
byte[] bytes = __message.getBytes("UTF-8");
_received=null;
socket.getOutputStream().write(
("POST /test/ HTTP/1.1\r\n"+
"Host: 127.0.0.1:"+_server.getConnectors()[0].getLocalPort()+"\r\n"+
"Content-Length: "+bytes.length+"\r\n"+
"\r\n").getBytes("UTF-8"));
socket.getOutputStream().write(bytes);
socket.getOutputStream().flush();
Thread.sleep(100);
byte[] buf=new byte[4096];
int len=socket.getInputStream().read(buf);
String result=new String(buf,0,len,"UTF-8");
assertTrue(result.startsWith("HTTP/1.1 401 Unauthorized"));
assertEquals(null,_received);
int n=result.indexOf("nonce=");
String nonce=result.substring(n+7,result.indexOf('"',n+7));
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] b= md.digest(String.valueOf(System.currentTimeMillis()).getBytes(StringUtil.__ISO_8859_1));
String cnonce=encode(b);
String digest="Digest username=\"testuser\" realm=\"test\" nonce=\""+nonce+"\" uri=\"/test/\" algorithm=MD5 response=\""+
newResponse("POST","/test/",cnonce,"testuser","test","password",nonce,"auth")+
"\" qop=auth nc="+NC+" cnonce=\""+cnonce+"\"";
_received=null;
socket.getOutputStream().write(
("POST /test/ HTTP/1.0\r\n"+
"Host: 127.0.0.1:"+_server.getConnectors()[0].getLocalPort()+"\r\n"+
"Content-Length: "+bytes.length+"\r\n"+
"Authorization: "+digest+"\r\n"+
"\r\n").getBytes("UTF-8"));
socket.getOutputStream().write(bytes);
socket.getOutputStream().flush();
result = IO.toString(socket.getInputStream());
assertTrue(result.startsWith("HTTP/1.1 200 OK"));
assertEquals(__message,_received);
}
public void testServerWithHttpClientStringContent() throws Exception
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setRealmResolver(new SimpleRealmResolver(new TestRealm()));
client.start();
String srvUrl = "http://127.0.0.1:" + _server.getConnectors()[0].getLocalPort() + "/test/";
ContentExchange ex = new ContentExchange();
ex.setMethod(HttpMethods.POST);
ex.setURL(srvUrl);
ex.setRequestContent(new ByteArrayBuffer(__message,"UTF-8"));
_received=null;
client.send(ex);
ex.waitForDone();
assertEquals(__message,_received);
assertEquals(200,ex.getResponseStatus());
}
public void testServerWithHttpClientStreamContent() throws Exception
{
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setRealmResolver(new SimpleRealmResolver(new TestRealm()));
client.start();
String srvUrl = "http://127.0.0.1:" + _server.getConnectors()[0].getLocalPort() + "/test/";
ContentExchange ex = new ContentExchange();
ex.setMethod(HttpMethods.POST);
ex.setURL(srvUrl);
ex.setRequestContentSource(new BufferedInputStream(new FileInputStream("src/test/resources/message.txt")));
_received=null;
client.send(ex);
ex.waitForDone();
String sent = IO.toString(new FileInputStream("src/test/resources/message.txt"));
assertEquals(sent,_received);
assertEquals(200,ex.getResponseStatus());
}
public static class TestRealm implements Realm
{
public String getPrincipal()
{
return "testuser";
}
public String getId()
{
return "test";
}
public String getCredentials()
{
return "password";
}
}
public static class PostServlet extends HttpServlet
{
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException
{
String received = IO.toString(request.getInputStream());
_received = received;
response.setStatus(200);
response.getWriter().println("Received "+received.length()+" bytes");
}
}
protected String newResponse(String method, String uri, String cnonce, String principal, String realm, String credentials, String nonce, String qop)
throws Exception
{
MessageDigest md = MessageDigest.getInstance("MD5");
// calc A1 digest
md.update(principal.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(realm.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(credentials.getBytes(StringUtil.__ISO_8859_1));
byte[] ha1 = md.digest();
// calc A2 digest
md.reset();
md.update(method.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(uri.getBytes(StringUtil.__ISO_8859_1));
byte[] ha2=md.digest();
md.update(TypeUtil.toString(ha1,16).getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(nonce.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(NC.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(cnonce.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(qop.getBytes(StringUtil.__ISO_8859_1));
md.update((byte)':');
md.update(TypeUtil.toString(ha2,16).getBytes(StringUtil.__ISO_8859_1));
byte[] digest=md.digest();
// check digest
return encode(digest);
}
private static String encode(byte[] data)
{
StringBuffer buffer = new StringBuffer();
for (int i=0; i<data.length; i++)
{
buffer.append(Integer.toHexString((data[i] & 0xf0) >>> 4));
buffer.append(Integer.toHexString(data[i] & 0x0f));
}
return buffer.toString();
}
}

View File

@ -0,0 +1,12 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc.
Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque
habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam
at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate
velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum.
Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum
eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa
sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam
consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque.
Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse
et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.