/*************************************************************************
* *
* SignServer: The OpenSource Automated Signing Server *
* *
* This software is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or any later version. *
* *
* See terms of license at gnu.org. *
* *
*************************************************************************/
package org.signserver.server;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import org.apache.log4j.Logger;
import org.junit.FixMethodOrder;
import org.junit.runners.MethodSorters;
import org.signserver.cli.spi.Command;
import org.signserver.cli.spi.CommandFailureException;
import org.signserver.cli.spi.IllegalCommandArgumentsException;
import org.signserver.cli.spi.UnexpectedCommandFailureException;
import org.signserver.client.cli.defaultimpl.SignDataGroupsCommand;
import org.signserver.client.cli.defaultimpl.SignDocumentCommand;
import org.signserver.common.AuthorizationRequiredException;
import org.signserver.common.GenericSignRequest;
import org.signserver.common.RequestContext;
import org.signserver.common.SignServerUtil;
import org.signserver.testutils.ModulesTestCase;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for the UsernamePasswordAuthorizer.
*
* @author Markus KilÄs
* @version $Id: UsernamePasswordAuthorizerTest.java 3465 2013-05-01 10:24:46Z netmackan $
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class UsernamePasswordAuthorizerTest extends ModulesTestCase {
private static final Logger LOG = Logger.getLogger(
UsernamePasswordAuthorizerTest.class);
@Before
public void setUp() throws Exception {
SignServerUtil.installBCProvider();
}
@Test
public void test00SetupDatabase() throws Exception {
addDummySigner1();
addSoftSODSigner(getSignerIdSODSigner1(), getSignerNameSODSigner1());
// Set auth type
workerSession.setWorkerProperty(getSignerIdDummy1(), "AUTHTYPE",
"org.signserver.server.UsernamePasswordAuthorizer");
// Add a user account: user1, foo123 (plain-text password)
workerSession.setWorkerProperty(getSignerIdDummy1(), "USER.USER1",
"foo123");
// Add a user account: user2, foo123 (SHA1 hashed password) = SHA1(foo123)
workerSession.setWorkerProperty(getSignerIdDummy1(), "USER.USER2",
"3b303d8b0364d9265c06adc8584258376150c9b5:SHA1");
// Add a user account: user3, foo123 (SHA1 hashed password and salted
// with "salt123") = SHA1(foo123salt123)
workerSession.setWorkerProperty(getSignerIdDummy1(), "USER.USER3",
"26c110963ad873c9b7db331e4c3130c266416d47:SHA1:salt123");
workerSession.setWorkerProperty(getSignerIdSODSigner1(), "USER.USER3",
"26c110963ad873c9b7db331e4c3130c266416d47:SHA1:salt123");
workerSession.reloadConfiguration(getSignerIdDummy1());
workerSession.reloadConfiguration(getSignerIdSODSigner1());
}
/**
* Tests that the worker throws an AuthorizationRequiredException if no
* username/password is supplied.
* @throws Exception in case of exception
*/
@Test
public void test01AuthorizationRequired() throws Exception {
final RequestContext context = new RequestContext();
final GenericSignRequest request =
new GenericSignRequest(1, "".getBytes());
// Without username password
try {
workerSession.process(getSignerIdDummy1(), request, context);
fail("No AuthorizationRequiredException thrown");
} catch (AuthorizationRequiredException ok) {
// OK
} catch (Exception ex) {
LOG.error("Wrong type of exception", ex);
fail("Exception: " + ex.getMessage());
}
// With other type of credentials
context.put(RequestContext.CLIENT_CREDENTIAL, new DummyCredential());
try {
workerSession.process(getSignerIdDummy1(), request, context);
fail("No AuthorizationRequiredException thrown");
} catch (AuthorizationRequiredException ok) {
// OK
} catch (Exception ex) {
LOG.error("Wrong type of exception", ex);
fail("Exception: " + ex.getMessage());
}
// With wrong password
context.put(RequestContext.CLIENT_CREDENTIAL,
new UsernamePasswordClientCredential("user1", "FOO1234"));
try {
workerSession.process(getSignerIdDummy1(), request, context);
fail("No AuthorizationRequiredException thrown");
} catch (AuthorizationRequiredException ok) {
// OK
} catch (Exception ex) {
LOG.error("Wrong type of exception", ex);
fail("Exception: " + ex.getMessage());
}
}
/**
* Tests that the worker accepts a correct user/password.
* @throws Exception in case of exception
*/
@Test
public void test02PlainTextPassword() throws Exception {
final RequestContext context = new RequestContext();
final GenericSignRequest request =
new GenericSignRequest(1, "".getBytes());
// With correct username password
context.put(RequestContext.CLIENT_CREDENTIAL,
new UsernamePasswordClientCredential("user1", "foo123"));
try {
workerSession.process(getSignerIdDummy1(), request, context);
} catch (AuthorizationRequiredException ex) {
fail("Username password not accepted!");
} catch (Exception ex) {
LOG.error("Wrong type of exception", ex);
fail("Exception: " + ex.getMessage());
}
}
/**
* Tests that the worker accepts a correct user/password.
* @throws Exception in case of exception
*/
@Test
public void test03HashedPassword() throws Exception {
final RequestContext context = new RequestContext();
final GenericSignRequest request =
new GenericSignRequest(1, "".getBytes());
// With correct username password
context.put(RequestContext.CLIENT_CREDENTIAL,
new UsernamePasswordClientCredential("user2", "foo123"));
try {
workerSession.process(getSignerIdDummy1(), request, context);
} catch (AuthorizationRequiredException ex) {
fail("Username password not accepted!");
} catch (Exception ex) {
LOG.error("Wrong type of exception", ex);
fail("Exception: " + ex.getMessage());
}
}
/**
* Tests that the worker accepts a correct user/password.
* @throws Exception in case of exception
*/
@Test
public void test04HashedAndSaltedPassword() throws Exception {
final RequestContext context = new RequestContext();
final GenericSignRequest request =
new GenericSignRequest(1, "".getBytes());
// With correct username password
context.put(RequestContext.CLIENT_CREDENTIAL,
new UsernamePasswordClientCredential("user3", "foo123"));
try {
workerSession.process(getSignerIdDummy1(), request, context);
} catch (AuthorizationRequiredException ex) {
fail("Username password not accepted!");
} catch (Exception ex) {
LOG.error("Wrong type of exception", ex);
fail("Exception: " + ex.getMessage());
}
}
@Test
public void test04HashedAndSaltedPasswordOverClientWS() throws Exception {
try {
byte[] res = execute(new SignDocumentCommand(), "signdocument", "-workerid",
String.valueOf(getSignerIdDummy1()), "-data", "",
"-username", "user3", "-password", "foo123", "-protocol", "CLIENTWS",
"-truststore", new File(getSignServerHome(), "p12/truststore.jks").getAbsolutePath(), "-truststorepwd", "changeit");
assertNotNull("No result", res);
assertNotSame("Empty result", 0, res.length);
} catch (IllegalCommandArgumentsException ex) {
LOG.error("Execution failed", ex);
fail(ex.getMessage());
}
}
@Test
public void test04HashedAndSaltedPasswordSODOverClientWS() throws Exception {
try {
byte[] res = execute(new SignDataGroupsCommand(), "signdatagroups", "-workerid",
String.valueOf(getSignerIdSODSigner1()), "-data", "1=value1&2=value2&3=value3",
"-username", "user3", "-password", "foo123", "-protocol", "CLIENTWS",
"-truststore", new File(getSignServerHome(), "p12/truststore.jks").getAbsolutePath(), "-truststorepwd", "changeit");
assertNotNull("No result", res);
assertNotSame("Empty result", 0, res.length);
} catch (IllegalCommandArgumentsException ex) {
LOG.error("Execution failed", ex);
fail(ex.getMessage());
}
}
@Test
public void test99TearDownDatabase() throws Exception {
removeWorker(getSignerIdDummy1());
workerSession.reloadConfiguration(getSignerIdDummy1());
removeWorker(getSignerIdSODSigner1());
workerSession.reloadConfiguration(getSignerIdSODSigner1());
}
private byte[] execute(Command command, String... args) throws IOException, IllegalCommandArgumentsException, CommandFailureException, UnexpectedCommandFailureException {
byte[] output;
final ByteArrayOutputStream out = new ByteArrayOutputStream();
System.setOut(new PrintStream(out));
try {
command.execute(args);
} finally {
output = out.toByteArray();
System.setOut(System.out);
System.out.write(output);
}
return output;
}
}