diff --git a/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java b/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java index 137f253139..ff4674f798 100644 --- a/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java +++ b/source/java/org/alfresco/repo/webdav/auth/AuthenticationFilter.java @@ -28,16 +28,22 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.transaction.UserTransaction; import org.alfresco.model.ContentModel; import org.alfresco.repo.security.authentication.AuthenticationException; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthenticationService; import org.alfresco.service.cmr.security.NoSuchPersonException; import org.alfresco.service.cmr.security.PersonService; +import org.alfresco.service.transaction.TransactionService; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; @@ -48,10 +54,18 @@ import org.springframework.web.context.support.WebApplicationContextUtils; */ public class AuthenticationFilter implements Filter { + // Debug logging + + private static Log logger = LogFactory.getLog(NTLMAuthenticationFilter.class); + // Authenticated user session object name public final static String AUTHENTICATION_USER = "_alfDAVAuthTicket"; + // Allow an authenitcation ticket to be passed as part of a request to bypass authentication + + private static final String ARG_TICKET = "ticket"; + // Servlet context private ServletContext m_context; @@ -61,6 +75,7 @@ public class AuthenticationFilter implements Filter private AuthenticationService m_authService; private PersonService m_personService; private NodeService m_nodeService; + private TransactionService m_transactionService; /** * Initialize the filter @@ -81,6 +96,7 @@ public class AuthenticationFilter implements Filter ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY); m_nodeService = serviceRegistry.getNodeService(); m_authService = serviceRegistry.getAuthenticationService(); + m_transactionService = serviceRegistry.getTransactionService(); m_personService = (PersonService) ctx.getBean("PersonService"); // transactional and permission-checked } @@ -137,12 +153,16 @@ public class AuthenticationFilter implements Filter try { // Authenticate the user - m_authService.authenticate(username, password.toCharArray()); + + m_authService.authenticate(username, password.toCharArray()); // Get the user node and home folder + NodeRef personNodeRef = m_personService.getPerson(username); NodeRef homeSpaceRef = (NodeRef) m_nodeService.getProperty(personNodeRef, ContentModel.PROP_HOMEFOLDER); + // Setup User object and Home space ID etc. + user = new WebDAVUser(username, m_authService.getCurrentTicket(), homeSpaceRef); httpReq.getSession().setAttribute(AUTHENTICATION_USER, user); @@ -156,6 +176,82 @@ public class AuthenticationFilter implements Filter // Do nothing, user object will be null } } + else + { + // Check if the request includes an authentication ticket + + String ticket = req.getParameter( ARG_TICKET); + + if ( ticket != null && ticket.length() > 0) + { + // Debug + + if ( logger.isDebugEnabled()) + logger.debug("Logon via ticket from " + req.getRemoteHost() + " (" + + req.getRemoteAddr() + ":" + req.getRemotePort() + ")" + " ticket=" + ticket); + + UserTransaction tx = null; + try + { + // Validate the ticket + + m_authService.validate(ticket); + + // Need to create the User instance if not already available + + String currentUsername = m_authService.getCurrentUserName(); + + // Start a transaction + + tx = m_transactionService.getUserTransaction(); + tx.begin(); + + NodeRef personRef = m_personService.getPerson(currentUsername); + user = new WebDAVUser( currentUsername, m_authService.getCurrentTicket(), personRef); + NodeRef homeRef = (NodeRef) m_nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER); + + // Check that the home space node exists - else Login cannot proceed + + if (m_nodeService.exists(homeRef) == false) + { + throw new InvalidNodeRefException(homeRef); + } + user.setHomeNode(homeRef); + + tx.commit(); + tx = null; + + // Store the User object in the Session - the authentication servlet will then proceed + + httpReq.getSession().setAttribute( AUTHENTICATION_USER, user); + } + catch (AuthenticationException authErr) + { + // Clear the user object to signal authentication failure + + user = null; + } + catch (Throwable e) + { + // Clear the user object to signal authentication failure + + user = null; + } + finally + { + try + { + if (tx != null) + { + tx.rollback(); + } + } + catch (Exception tex) + { + } + } + } + } // Check if the user is authenticated, if not then prompt again diff --git a/source/java/org/alfresco/repo/webdav/auth/NTLMAuthenticationFilter.java b/source/java/org/alfresco/repo/webdav/auth/NTLMAuthenticationFilter.java index 0d489e5e25..51f2177fbd 100644 --- a/source/java/org/alfresco/repo/webdav/auth/NTLMAuthenticationFilter.java +++ b/source/java/org/alfresco/repo/webdav/auth/NTLMAuthenticationFilter.java @@ -54,6 +54,7 @@ import org.alfresco.repo.security.authentication.MD4PasswordEncoderImpl; import org.alfresco.repo.security.authentication.NTLMMode; import org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken; import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.InvalidNodeRefException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.security.AuthenticationService; @@ -81,6 +82,10 @@ public class NTLMAuthenticationFilter implements Filter public final static String AUTHENTICATION_USER = "_alfDAVAuthTicket"; + // Allow an authenitcation ticket to be passed as part of a request to bypass authentication + + private static final String ARG_TICKET = "ticket"; + // NTLM flags mask, used to mask out features that are not supported private static final int NTLM_FLAGS = NTLM.Flag56Bit + NTLM.FlagLanManKey + NTLM.FlagNegotiateNTLM + @@ -285,7 +290,86 @@ public class NTLMAuthenticationFilter implements Filter if ( authHdr == null) { - // Debug + // Check if the request includes an authentication ticket + + String ticket = req.getParameter( ARG_TICKET); + + if ( ticket != null && ticket.length() > 0) + { + // Debug + + if ( logger.isDebugEnabled()) + logger.debug("Logon via ticket from " + req.getRemoteHost() + " (" + + req.getRemoteAddr() + ":" + req.getRemotePort() + ")" + " ticket=" + ticket); + + UserTransaction tx = null; + try + { + // Validate the ticket + + m_authService.validate(ticket); + + // Need to create the User instance if not already available + + String currentUsername = m_authService.getCurrentUserName(); + + // Start a transaction + + tx = m_transactionService.getUserTransaction(); + tx.begin(); + + NodeRef personRef = m_personService.getPerson(currentUsername); + user = new WebDAVUser( currentUsername, m_authService.getCurrentTicket(), personRef); + NodeRef homeRef = (NodeRef) m_nodeService.getProperty(personRef, ContentModel.PROP_HOMEFOLDER); + + // Check that the home space node exists - else Login cannot proceed + + if (m_nodeService.exists(homeRef) == false) + { + throw new InvalidNodeRefException(homeRef); + } + user.setHomeNode(homeRef); + + tx.commit(); + tx = null; + + // Store the User object in the Session - the authentication servlet will then proceed + + req.getSession().setAttribute( AUTHENTICATION_USER, user); + + // Chain to the next filter + + chain.doFilter(sreq, sresp); + return; + } + catch (AuthenticationException authErr) + { + // Clear the user object to signal authentication failure + + user = null; + } + catch (Throwable e) + { + // Clear the user object to signal authentication failure + + user = null; + } + finally + { + try + { + if (tx != null) + { + tx.rollback(); + } + } + catch (Exception tex) + { + } + } + } + + // Debug if ( logger.isDebugEnabled()) logger.debug("New NTLM auth request from " + req.getRemoteHost() + " (" + diff --git a/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java b/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java index 39becd73ef..2f0e8ad1a0 100644 --- a/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java +++ b/source/java/org/alfresco/repo/webservice/repository/RepositoryWebService.java @@ -578,18 +578,14 @@ public class RepositoryWebService extends AbstractWebService implements // create the web service ClassDefinition type from the data dictionary TypeDefinition ClassDefinition typeDef = Utils.setupClassDefObject(ddTypeDef); - // create the web service ClassDefinition types to represent the aspects - ClassDefinition[] aspectDefs = null; - List aspects = ddTypeDef.getDefaultAspects(); - if (aspects != null) + Set aspectsQNames = this.nodeService.getAspects(nodeRef); + ClassDefinition[] aspectDefs = new ClassDefinition[aspectsQNames.size()]; + int pos = 0; + for (QName aspectQName : aspectsQNames) { - aspectDefs = new ClassDefinition[aspects.size()]; - int pos = 0; - for (AspectDefinition ddAspectDef : aspects) - { - aspectDefs[pos] = Utils.setupClassDefObject(ddAspectDef); - pos++; - } + AspectDefinition aspectDef = this.dictionaryService.getAspect(aspectQName); + aspectDefs[pos] = Utils.setupClassDefObject(aspectDef); + pos++; } return new NodeDefinition(typeDef, aspectDefs);