Merged HEAD-BUG-FIX (4.3/Cloud) to HEAD (4.3/Cloud)

63086: Merged V4.2-BUG-FIX (4.2.2) to HEAD-BUG-FIX (Cloud/4.3)
      62850: Merged V4.1-BUG-FIX (4.1.8) to V4.2-BUG-FIX (4.2.2)
         62709: MNT-10644: autoCreatePeopleOnLogin=false allows unauthorized users to log in via CIFS
            Force user creation on CIFS log in only if autoCreatePeopleOnLogin=true. Add unit tests for EnterpriseCifsAuthenticator
   		 and PassthruCifsAuthenticator.
      62968: MNT-10644: autoCreatePeopleOnLogin=false allows unauthorized users to log in via CIFS
         Fix CifsAuthenticatorKerberosTest: to check person existence in V4.2-BUG-FIX RunAsUser is required to be set


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@64265 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2014-03-14 15:49:58 +00:00
parent 6a048b6b85
commit 71324ac54f
6 changed files with 395 additions and 1 deletions

View File

@@ -436,7 +436,10 @@ public class Repository01TestSuite extends TestSuite
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.test.junitrules.ApplicationContextInitTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.test.junitrules.TemporaryNodesTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.test.junitrules.TemporarySitesTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.filesys.auth.cifs.CifsAuthenticatorKerberosTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.filesys.auth.cifs.CifsAuthenticatorPassthruTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.CronTriggerBeanTest.class));
suite.addTest(new JUnit4TestAdapter(org.alfresco.util.CronTriggerBeanSystemTest.class));
}
}

View File

@@ -0,0 +1,157 @@
package org.alfresco.filesys.auth.cifs;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.sync.UserRegistrySynchronizer;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.context.ApplicationContext;
public class CifsAuthenticatorKerberosTest
{
public static final String[] CONFIG_LOCATIONS = new String[] { "classpath:alfresco/application-context.xml",
"classpath:alfresco/filesys/auth/cifs/test-kerberos-context.xml"
};
private static ApplicationContext ctx = null;
private PersonService personService;
private TransactionService transactionService;
private EnterpriseCifsAuthenticator cifsAuthenticator;
private String userExistingLocal = "user1." + GUID.generate();
private String userMissingLocal = "user2." + GUID.generate();
@BeforeClass
public static void init()
{
ApplicationContextHelper.setUseLazyLoading(false);
ApplicationContextHelper.setNoAutoStart(true);
ctx = ApplicationContextHelper.getApplicationContext(CONFIG_LOCATIONS);
}
@Before
public void before() throws Exception
{
this.personService = (PersonService)ctx.getBean("personService");
this.transactionService = (TransactionService)ctx.getBean("transactionService");
this.cifsAuthenticator = (EnterpriseCifsAuthenticator)ctx.getBean("cifsAuthenticator");
// create only user1 in local repository
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
@SuppressWarnings("synthetic-access")
public Void execute() throws Throwable
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
// create person properties
PropertyMap personProps = new PropertyMap();
personProps.put(ContentModel.PROP_USERNAME, userExistingLocal);
personProps.put(ContentModel.PROP_FIRSTNAME, userExistingLocal);
personProps.put(ContentModel.PROP_LASTNAME, userExistingLocal);
personProps.put(ContentModel.PROP_EMAIL, userExistingLocal+"@email.com");
personService.createPerson(personProps);
AuthenticationUtil.popAuthentication();
return null;
}
}, false, true);
}
private UserRegistrySynchronizer makeUserRegistrySynchronizerStub(final boolean autoCreatePeopleOnLogin)
{
UserRegistrySynchronizer stub = mock(UserRegistrySynchronizer.class);
when(stub.createMissingPerson(anyString())).thenAnswer(new Answer<Boolean>()
{
public Boolean answer(InvocationOnMock invocation) throws Throwable
{
Object[] args = invocation.getArguments();
String userName = (String) args[0];
if (userName != null && !userName.equals(AuthenticationUtil.getSystemUserName()))
{
PersonService personServiceStub = mock(PersonService.class);
when(personServiceStub.createMissingPeople()).thenReturn(true);
if (autoCreatePeopleOnLogin && personServiceStub.createMissingPeople())
{
AuthorityType authorityType = AuthorityType.getAuthorityType(userName);
if (authorityType == AuthorityType.USER)
{
personService.getPerson(userName);
return true;
}
}
}
return false;
}
});
return stub;
}
@Test
public void testExistingUserMappingWhenAutoCreateNotAllowed()
{
UserRegistrySynchronizer userRegistrySynchronizer = makeUserRegistrySynchronizerStub(false);
((AbstractAuthenticationComponent) cifsAuthenticator.getAuthenticationComponent()).setUserRegistrySynchronizer(userRegistrySynchronizer);
String username = cifsAuthenticator.mapUserNameToPerson(userExistingLocal, false);
assertEquals("Existing local user should be mapped to authenticated AD user", username, userExistingLocal);
}
@Test
public void testExistingUserMappingWhenAutoCreateAllowed()
{
UserRegistrySynchronizer userRegistrySynchronizer = makeUserRegistrySynchronizerStub(true);
((AbstractAuthenticationComponent) cifsAuthenticator.getAuthenticationComponent()).setUserRegistrySynchronizer(userRegistrySynchronizer);
String username = cifsAuthenticator.mapUserNameToPerson(userExistingLocal, false);
assertEquals("Existing local user should be mapped to authenticated AD user", username, userExistingLocal);
}
@Test
public void testMissingUserMappingWhenAutoCreateNotAllowed()
{
UserRegistrySynchronizer userRegistrySynchronizer = makeUserRegistrySynchronizerStub(false);
((AbstractAuthenticationComponent) cifsAuthenticator.getAuthenticationComponent()).setUserRegistrySynchronizer(userRegistrySynchronizer);
try
{
cifsAuthenticator.mapUserNameToPerson(userMissingLocal, false);
fail("User that does not exist in repository should not login when autoCreatePeopleOnLogin is not allowed");
}
catch (AuthenticationException expected)
{
}
}
@Test
public void testMissingUserMappingWhenAutoCreateAllowed()
{
UserRegistrySynchronizer userRegistrySynchronizer = makeUserRegistrySynchronizerStub(true);
((AbstractAuthenticationComponent) cifsAuthenticator.getAuthenticationComponent()).setUserRegistrySynchronizer(userRegistrySynchronizer);
String username = cifsAuthenticator.mapUserNameToPerson(userMissingLocal, false);
assertEquals("User that does not exist in repository can login when autoCreatePeopleOnLogin is allowed", username, userMissingLocal);
// personService.personExists requires RunAsUser to be set
AuthenticationUtil.setRunAsUser(AuthenticationUtil.getSystemUserName());
assertTrue(personService.personExists(userMissingLocal));
}
}

View File

@@ -0,0 +1,198 @@
package org.alfresco.filesys.auth.cifs;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.alfresco.filesys.alfresco.AlfrescoClientInfo;
import org.alfresco.jlan.server.SrvSession;
import org.alfresco.jlan.server.auth.ClientInfo;
import org.alfresco.jlan.server.auth.ICifsAuthenticator;
import org.alfresco.jlan.server.auth.passthru.AuthenticateSession;
import org.alfresco.jlan.server.auth.passthru.PassthruDetails;
import org.alfresco.jlan.smb.server.SMBSrvSession;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.sync.UserRegistrySynchronizer;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.GUID;
import org.alfresco.util.PropertyMap;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.context.ApplicationContext;
public class CifsAuthenticatorPassthruTest
{
private static ApplicationContext ctx = null;
private PersonService personService;
private TransactionService transactionService;
private NodeService nodeService;
private PassthruCifsAuthenticator cifsAuthenticator;
private AuthenticationContext authenticationContext;
private String userExistingLocal = "user1." + GUID.generate();
private String userMissingLocal = "user2." + GUID.generate();
@BeforeClass
public static void init()
{
ApplicationContextHelper.setUseLazyLoading(false);
ApplicationContextHelper.setNoAutoStart(true);
ctx = ApplicationContextHelper.getApplicationContext();
}
@Before
public void before() throws Exception
{
this.personService = (PersonService) ctx.getBean("personService");
this.transactionService = (TransactionService) ctx.getBean("transactionService");
this.nodeService = (NodeService) ctx.getBean("nodeService");
this.authenticationContext = (AuthenticationContext) ctx.getBean("authenticationContext");
// cannot get bean from context directly because of side affects from passthruServers.afterPropertiesSet
this.cifsAuthenticator = new PassthruCifsAuthenticator();
this.cifsAuthenticator.setTransactionService(transactionService);
// passthru-authentication-context.xml : NTLMAuthenticationComponentImpl is used for passthru
AbstractAuthenticationComponent ac = new org.alfresco.repo.security.authentication.ntlm.NTLMAuthenticationComponentImpl();
ac.setPersonService(personService);
ac.setTransactionService(transactionService);
ac.setNodeService(nodeService);
ac.setAuthenticationContext(authenticationContext);
this.cifsAuthenticator.setAuthenticationComponent(ac);
this.cifsAuthenticator.setAuthenticationService(mock(org.alfresco.repo.security.authentication.AuthenticationServiceImpl.class));
// create only user1 in local repository
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
@SuppressWarnings("synthetic-access")
public Void execute() throws Throwable
{
AuthenticationUtil.pushAuthentication();
AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
// create person properties
PropertyMap personProps = new PropertyMap();
personProps.put(ContentModel.PROP_USERNAME, userExistingLocal);
personProps.put(ContentModel.PROP_FIRSTNAME, userExistingLocal);
personProps.put(ContentModel.PROP_LASTNAME, userExistingLocal);
personProps.put(ContentModel.PROP_EMAIL, userExistingLocal + "@email.com");
personService.createPerson(personProps);
AuthenticationUtil.popAuthentication();
return null;
}
}, false, true);
}
private UserRegistrySynchronizer makeUserRegistrySynchronizerStub(final boolean autoCreatePeopleOnLogin)
{
UserRegistrySynchronizer stub = mock(UserRegistrySynchronizer.class);
when(stub.createMissingPerson(anyString())).thenAnswer(new Answer<Boolean>()
{
public Boolean answer(InvocationOnMock invocation) throws Throwable
{
Object[] args = invocation.getArguments();
String userName = (String) args[0];
if (userName != null && !userName.equals(AuthenticationUtil.getSystemUserName()))
{
PersonService personServiceStub = mock(PersonService.class);
when(personServiceStub.createMissingPeople()).thenReturn(true);
if (autoCreatePeopleOnLogin && personServiceStub.createMissingPeople())
{
AuthorityType authorityType = AuthorityType.getAuthorityType(userName);
if (authorityType == AuthorityType.USER)
{
personService.getPerson(userName);
return true;
}
}
}
return false;
}
});
return stub;
}
private class TestContext
{
protected ClientInfo client;
protected SrvSession sess;
protected TestContext(ClientInfo client, SrvSession sess)
{
this.client = client;
this.sess = sess;
}
}
private TestContext prepareTestConditions(boolean autoCreatePeopleOnLogin, String userName) throws Exception
{
UserRegistrySynchronizer userRegistrySynchronizer = makeUserRegistrySynchronizerStub(autoCreatePeopleOnLogin);
((AbstractAuthenticationComponent) cifsAuthenticator.getAuthenticationComponent()).setUserRegistrySynchronizer(userRegistrySynchronizer);
ClientInfo client = mock(AlfrescoClientInfo.class);
client.setUserName(userName);
SrvSession sess = mock(SMBSrvSession.class);
sess.setUniqueId(userName);
// add getter to the original class, otherwise reflection should be used to add session to private field
AuthenticateSession as = mock(AuthenticateSession.class);
// assume successful passthru authentication
doNothing().when(as).doSessionSetup(anyString(), anyString(), anyString(), any(byte[].class), any(byte[].class), anyInt());
PassthruDetails pd = new PassthruDetails(sess, as);
cifsAuthenticator.getSessions().put(userName, pd);
return new TestContext(client, sess);
}
@Test
public void testExistingUserAuthenticationWhenAutoCreateNotAllowed() throws Exception
{
TestContext tc = prepareTestConditions(false, userExistingLocal);
int status = cifsAuthenticator.authenticateUser(tc.client, tc.sess, 0);
assertEquals("Access should be allowed if user exists in local repository", status, ICifsAuthenticator.AUTH_ALLOW);
}
@Test
public void testExistingUserAuthenticationWhenAutoCreateAllowed() throws Exception
{
TestContext tc = prepareTestConditions(true, userExistingLocal);
int status = cifsAuthenticator.authenticateUser(tc.client, tc.sess, 0);
assertEquals("Access should be allowed if user exists in local repository", status, ICifsAuthenticator.AUTH_ALLOW);
}
@Test
public void testMissingUserAuthenticationWhenAutoCreateNotAllowed() throws Exception
{
TestContext tc = prepareTestConditions(false, userMissingLocal);
int status = cifsAuthenticator.authenticateUser(tc.client, tc.sess, 0);
assertEquals("User that does not exist in repository should not login when autoCreatePeopleOnLogin is not allowed",
status, ICifsAuthenticator.AUTH_DISALLOW);
}
@Test
public void testMissingUserAuthenticationWhenAutoCreateAllowed() throws Exception
{
TestContext tc = prepareTestConditions(true, userMissingLocal);
int status = cifsAuthenticator.authenticateUser(tc.client, tc.sess, 0);
assertEquals("User that does not exist in repository can login when autoCreatePeopleOnLogin is allowed",
status, ICifsAuthenticator.AUTH_ALLOW);
}
}