mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
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:
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user