Merged enterprise features

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2746 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Paul Holmes-Higgin
2006-05-03 18:34:13 +00:00
parent 405c00bd8e
commit c37ff8805c
83 changed files with 15809 additions and 9 deletions

View File

@@ -0,0 +1,209 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.jaas;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.LanguageCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.RealmCallback;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
/**
* JAAS based authentication
*
* The user name and password are picked up from login.
*
* The other configurable parameters are:
* realm - the authentication realm if required,
* and the entry name to use from the login context.
*
* You will need to be familiar with the JAAS authentication process to set this up.
*
* In summary you will need to configure java.security (in the lib/security directory of the jre you are using)
* to find a jaas configuration.
*
* This entry could be used if you want to put the login configuration in the same place (in the lib/security directory of the jre you are using)
*
* <code>
* login.config.url.1=file:${java.home}/lib/security/java.login.config
* </code>
*
* Example configuration entries for Kerberos would be:
*
* <code>
* Alfresco {
* com.sun.security.auth.module.Krb5LoginModule sufficient;
* };
*
* com.sun.net.ssl.client {
* com.sun.security.auth.module.Krb5LoginModule sufficient;
* };
*
* other {
* com.sun.security.auth.module.Krb5LoginModule sufficient;
* };
* </code>
*
* This sets up authentication using Kerberos for Alfresco and some defaults that would use the same mechanism if sasl failed for example.
*
* You could use kerberos and LDAP combined against an Active Directory server.
*
* @author Andy Hind
*/
public class JAASAuthenticationComponent extends AbstractAuthenticationComponent
{
/**
* A key into the login config that defines the authentication mechamisms required.
*/
private String jaasConfigEntryName = "Alfresco";
/**
* A default realm
*/
private String realm = null;
public JAASAuthenticationComponent()
{
super();
}
// Springification
public void setJaasConfigEntryName(String jaasConfigEntryName)
{
this.jaasConfigEntryName = jaasConfigEntryName;
}
public void setRealm(String realm)
{
this.realm = realm;
}
/**
* Jaas does not support guest login
*/
@Override
protected boolean implementationAllowsGuestLogin()
{
return false;
}
/**
* Implement Authentication
*/
public void authenticate(String userName, char[] password) throws AuthenticationException
{
LoginContext lc;
try
{
lc = new LoginContext(jaasConfigEntryName, new SimpleCallback(userName, realm, password));
}
catch (LoginException e)
{
throw new AuthenticationException("Login Failed", e);
}
try
{
lc.login();
// Login has gone through OK, set up the acegi context
setCurrentUser(userName);
}
catch (LoginException e)
{
throw new AuthenticationException("Login Failed", e);
}
}
/**
* Simple call back class to support the common requirements.
*
* @author Andy Hind
*/
private static class SimpleCallback implements CallbackHandler
{
String userName;
String realm;
char[] password;
SimpleCallback(String userName, String realm, char[] password)
{
this.userName = userName;
this.realm = realm;
this.password = password;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++)
{
if (callbacks[i] instanceof AuthorizeCallback)
{
AuthorizeCallback cb = (AuthorizeCallback) callbacks[i];
cb.setAuthorized(false);
}
else if (callbacks[i] instanceof LanguageCallback)
{
LanguageCallback cb = (LanguageCallback) callbacks[i];
cb.setLocale(I18NUtil.getLocale());
}
else if (callbacks[i] instanceof NameCallback)
{
NameCallback cb = (NameCallback) callbacks[i];
cb.setName(userName);
}
else if (callbacks[i] instanceof PasswordCallback)
{
PasswordCallback cb = (PasswordCallback) callbacks[i];
cb.setPassword(password);
}
else if (callbacks[i] instanceof RealmCallback)
{
RealmCallback cb = (RealmCallback) callbacks[i];
cb.setText(realm);
}
else
{
throw new UnsupportedCallbackException(callbacks[i]);
}
}
}
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ldap;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
import org.alfresco.repo.security.authentication.AbstractAuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationException;
/**
* Currently expects the cn name of the user which is in a fixed location.
*
* @author Andy Hind
*/
public class LDAPAuthenticationComponentImpl extends AbstractAuthenticationComponent
{
private String userNameFormat;
private LDAPInitialDirContextFactory ldapInitialContextFactory;
public LDAPAuthenticationComponentImpl()
{
super();
}
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
{
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
}
public void setUserNameFormat(String userNameFormat)
{
this.userNameFormat = userNameFormat;
}
/**
* Implement the authentication method
*/
public void authenticate(String userName, char[] password) throws AuthenticationException
{
InitialDirContext ctx = null;
try
{
ctx = ldapInitialContextFactory.getInitialDirContext(String.format(userNameFormat, new Object[]{userName}), new String(password));
// Authentication has been successful.
// Set the current user, they are now authenticated.
setCurrentUser(userName);
}
finally
{
if(ctx != null)
{
try
{
ctx.close();
}
catch (NamingException e)
{
clearCurrentSecurityContext();
throw new AuthenticationException("Failed to close connection", e);
}
}
}
}
@Override
protected boolean implementationAllowsGuestLogin()
{
InitialDirContext ctx = null;
try
{
ctx = ldapInitialContextFactory.getDefaultIntialDirContext();
return true;
}
catch(Exception e)
{
return false;
}
finally
{
if(ctx != null)
{
try
{
ctx.close();
}
catch (NamingException e)
{
throw new AuthenticationException("Failed to close connection", e);
}
}
}
}
}

View File

@@ -0,0 +1,695 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ldap;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.importer.ExportSource;
import org.alfresco.repo.importer.ExportSourceImporterException;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ApplicationContextHelper;
import org.alfresco.util.EqualsHelper;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
public class LDAPGroupExportSource implements ExportSource, InitializingBean
{
private static Log s_logger = LogFactory.getLog(LDAPGroupExportSource.class);
private String groupQuery = "(objectclass=groupOfNames)";
private String searchBase;
private String groupIdAttributeName = "cn";
private String userIdAttributeName = "uid";
private String groupType = "groupOfNames";
private String personType = "inetOrgPerson";
private LDAPInitialDirContextFactory ldapInitialContextFactory;
private NamespaceService namespaceService;
private String memberAttribute = "member";
private boolean errorOnMissingMembers = false;
private QName viewRef;
private QName viewId;
private QName viewAssociations;
private QName childQName;
private QName viewValueQName;
private QName viewIdRef;
public LDAPGroupExportSource()
{
super();
}
public void setGroupIdAttributeName(String groupIdAttributeName)
{
this.groupIdAttributeName = groupIdAttributeName;
}
public void setGroupQuery(String groupQuery)
{
this.groupQuery = groupQuery;
}
public void setGroupType(String groupType)
{
this.groupType = groupType;
}
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
{
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
}
public void setMemberAttribute(String memberAttribute)
{
this.memberAttribute = memberAttribute;
}
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public void setPersonType(String personType)
{
this.personType = personType;
}
public void setSearchBase(String searchBase)
{
this.searchBase = searchBase;
}
public void setUserIdAttributeName(String userIdAttributeName)
{
this.userIdAttributeName = userIdAttributeName;
}
public void setErrorOnMissingMembers(boolean errorOnMissingMembers)
{
this.errorOnMissingMembers = errorOnMissingMembers;
}
public void generateExport(XMLWriter writer)
{
HashSet<Group> rootGroups = new HashSet<Group>();
HashMap<String, Group> lookup = new HashMap<String, Group>();
HashSet<SecondaryLink> secondaryLinks = new HashSet<SecondaryLink>();
buildGroupsAndRoots(rootGroups, lookup, secondaryLinks);
buildXML(rootGroups, lookup, secondaryLinks, writer);
}
private void buildXML(HashSet<Group> rootGroups, HashMap<String, Group> lookup,
HashSet<SecondaryLink> secondaryLinks, XMLWriter writer)
{
Collection<String> prefixes = namespaceService.getPrefixes();
QName childQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "childName", namespaceService);
try
{
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName
.toPrefixString(), null, ContentModel.TYPE_PERSON.toPrefixString(namespaceService));
writer.startDocument();
for (String prefix : prefixes)
{
if (!prefix.equals("xml"))
{
String uri = namespaceService.getNamespaceURI(prefix);
writer.startPrefixMapping(prefix, uri);
}
}
writer.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view",
NamespaceService.REPOSITORY_VIEW_PREFIX + ":" + "view", new AttributesImpl());
// Create group structure
for (Group group : rootGroups)
{
addRootGroup(lookup, group, writer);
}
// Create secondary links.
for (SecondaryLink sl : secondaryLinks)
{
addSecondarylink(lookup, sl, writer);
}
for (String prefix : prefixes)
{
if (!prefix.equals("xml"))
{
writer.endPrefixMapping(prefix);
}
}
writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view", NamespaceService.REPOSITORY_VIEW_PREFIX
+ ":" + "view");
writer.endDocument();
}
catch (SAXException e)
{
throw new ExportSourceImporterException("Failed to create file for import.", e);
}
}
private void addSecondarylink(HashMap<String, Group> lookup, SecondaryLink sl, XMLWriter writer)
throws SAXException
{
String fromId = lookup.get(sl.from).guid;
String toId = lookup.get(sl.to).guid;
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, fromId);
writer.startElement(viewRef.getNamespaceURI(), viewRef.getLocalName(),
viewRef.toPrefixString(namespaceService), attrs);
writer.startElement(viewAssociations.getNamespaceURI(), viewAssociations.getLocalName(), viewAssociations
.toPrefixString(namespaceService), new AttributesImpl());
writer.startElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService), new AttributesImpl());
AttributesImpl attrsRef = new AttributesImpl();
attrsRef.addAttribute(viewIdRef.getNamespaceURI(), viewIdRef.getLocalName(), viewIdRef.toPrefixString(), null, toId);
attrsRef.addAttribute(childQName.getNamespaceURI(), childQName.getLocalName(), childQName.toPrefixString(),
null, QName.createQName(ContentModel.USER_MODEL_URI, sl.to).toPrefixString(namespaceService));
writer.startElement(viewRef.getNamespaceURI(), viewRef.getLocalName(),
viewRef.toPrefixString(namespaceService), attrsRef);
writer.endElement(viewRef.getNamespaceURI(), viewRef.getLocalName(), viewRef.toPrefixString(namespaceService));
writer.endElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService));
writer.endElement(viewAssociations.getNamespaceURI(), viewAssociations.getLocalName(), viewAssociations
.toPrefixString(namespaceService));
writer.endElement(viewRef.getNamespaceURI(), viewRef.getLocalName(), viewRef.toPrefixString(namespaceService));
}
private void addRootGroup(HashMap<String, Group> lookup, Group group, XMLWriter writer) throws SAXException
{
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName
.toPrefixString(), null, QName.createQName(ContentModel.USER_MODEL_URI, group.gid).toPrefixString(
namespaceService));
attrs.addAttribute(viewId.getNamespaceURI(), viewId.getLocalName(), viewId
.toPrefixString(), null, group.guid);
writer.startElement(ContentModel.TYPE_AUTHORITY_CONTAINER.getNamespaceURI(),
ContentModel.TYPE_AUTHORITY_CONTAINER.getLocalName(), ContentModel.TYPE_AUTHORITY_CONTAINER
.toPrefixString(namespaceService), attrs);
writer.startElement(ContentModel.PROP_AUTHORITY_NAME.getNamespaceURI(), ContentModel.PROP_AUTHORITY_NAME
.getLocalName(), ContentModel.PROP_AUTHORITY_NAME.toPrefixString(namespaceService),
new AttributesImpl());
writer.characters(group.gid.toCharArray(), 0, group.gid.length());
writer.endElement(ContentModel.PROP_AUTHORITY_NAME.getNamespaceURI(), ContentModel.PROP_AUTHORITY_NAME
.getLocalName(), ContentModel.PROP_AUTHORITY_NAME.toPrefixString(namespaceService));
if (group.members.size() > 0)
{
writer.startElement(ContentModel.PROP_MEMBERS.getNamespaceURI(), ContentModel.PROP_MEMBERS.getLocalName(),
ContentModel.PROP_MEMBERS.toPrefixString(namespaceService), new AttributesImpl());
for (String member : group.members)
{
writer.startElement(viewValueQName.getNamespaceURI(), viewValueQName.getLocalName(), viewValueQName
.toPrefixString(namespaceService), new AttributesImpl());
writer.characters(member.toCharArray(), 0, member.length());
writer.endElement(viewValueQName.getNamespaceURI(), viewValueQName.getLocalName(), viewValueQName
.toPrefixString(namespaceService));
}
writer.endElement(ContentModel.PROP_MEMBERS.getNamespaceURI(), ContentModel.PROP_MEMBERS.getLocalName(),
ContentModel.PROP_MEMBERS.toPrefixString(namespaceService));
}
for (Group child : group.children)
{
addgroup(lookup, child, writer);
}
writer.endElement(ContentModel.TYPE_AUTHORITY_CONTAINER.getNamespaceURI(),
ContentModel.TYPE_AUTHORITY_CONTAINER.getLocalName(), ContentModel.TYPE_AUTHORITY_CONTAINER
.toPrefixString(namespaceService));
}
private void addgroup(HashMap<String, Group> lookup, Group group, XMLWriter writer) throws SAXException
{
AttributesImpl attrs = new AttributesImpl();
writer.startElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService), attrs);
addRootGroup(lookup, group, writer);
writer.endElement(ContentModel.ASSOC_MEMBER.getNamespaceURI(), ContentModel.ASSOC_MEMBER.getLocalName(),
ContentModel.ASSOC_MEMBER.toPrefixString(namespaceService));
}
private void buildGroupsAndRoots(HashSet<Group> rootGroups, HashMap<String, Group> lookup,
HashSet<SecondaryLink> secondaryLinks)
{
InitialDirContext ctx = null;
try
{
ctx = ldapInitialContextFactory.getDefaultIntialDirContext();
SearchControls userSearchCtls = new SearchControls();
userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration searchResults = ctx.search(searchBase, groupQuery, userSearchCtls);
while (searchResults.hasMoreElements())
{
SearchResult result = (SearchResult) searchResults.next();
Attributes attributes = result.getAttributes();
Attribute gidAttribute = attributes.get(groupIdAttributeName);
if(gidAttribute == null)
{
throw new ExportSourceImporterException("Group returned by group search does not have mandatory group id attribute "+attributes);
}
String gid = (String) gidAttribute.get(0);
Group group = lookup.get(gid);
if (group == null)
{
group = new Group(gid);
lookup.put(group.gid, group);
rootGroups.add(group);
}
Attribute memAttribute = attributes.get(memberAttribute);
// check for null
if (memAttribute != null)
{
for (int i = 0; i < memAttribute.size(); i++)
{
String attribute = (String) memAttribute.get(i);
if (attribute != null)
{
group.distinguishedNames.add(attribute);
}
}
}
}
if (s_logger.isDebugEnabled())
{
s_logger.debug("Found " + lookup.size());
}
for (Group group : lookup.values())
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("Linking " + group.gid);
}
for (String dn : group.distinguishedNames)
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("... " + dn);
}
String id;
Boolean isGroup = null;
SearchControls memberSearchCtls = new SearchControls();
memberSearchCtls.setSearchScope(SearchControls.OBJECT_SCOPE);
NamingEnumeration memberSearchResults;
try
{
memberSearchResults = ctx.search(dn, "(objectClass=*)", memberSearchCtls);
}
catch (NamingException e)
{
if (errorOnMissingMembers)
{
throw e;
}
s_logger.warn("Failed to resolve distinguished name: " + dn);
continue;
}
while (memberSearchResults.hasMoreElements())
{
id = null;
SearchResult result;
try
{
result = (SearchResult) memberSearchResults.next();
}
catch (NamingException e)
{
if (errorOnMissingMembers)
{
throw e;
}
s_logger.warn("Failed to resolve distinguished name: " + dn);
continue;
}
Attributes attributes = result.getAttributes();
Attribute objectclass = attributes.get("objectclass");
if(objectclass == null)
{
throw new ExportSourceImporterException("Failed to find attribute objectclass for DN "+dn);
}
for (int i = 0; i < objectclass.size(); i++)
{
String testType;
try
{
testType = (String) objectclass.get(i);
}
catch (NamingException e)
{
if (errorOnMissingMembers)
{
throw e;
}
s_logger.warn("Failed to resolve object class attribute for distinguished name: " + dn);
continue;
}
if (testType.equals(groupType))
{
isGroup = true;
try
{
Attribute groupIdAttribute = attributes.get(groupIdAttributeName);
if(groupIdAttribute == null)
{
throw new ExportSourceImporterException("Group missing group id attribute DN ="+dn + " att = "+groupIdAttributeName);
}
id = (String) groupIdAttribute.get(0);
}
catch (NamingException e)
{
if (errorOnMissingMembers)
{
throw e;
}
s_logger.warn("Failed to resolve group identifier "
+ groupIdAttributeName + " for distinguished name: " + dn);
id = "Unknown sub group";
}
break;
}
else if (testType.equals(personType))
{
isGroup = false;
try
{
Attribute userIdAttribute = attributes.get(userIdAttributeName);
if(userIdAttribute == null)
{
throw new ExportSourceImporterException("User missing user id attribute DN ="+dn + " att = "+userIdAttributeName);
}
id = (String) userIdAttribute.get(0);
}
catch (NamingException e)
{
if (errorOnMissingMembers)
{
throw e;
}
s_logger.warn("Failed to resolve group identifier "
+ userIdAttributeName + " for distinguished name: " + dn);
id = "Unknown member";
}
break;
}
}
if (id != null)
{
if (isGroup == null)
{
throw new ExportSourceImporterException("Type not recognised for DN"+dn);
}
else if (isGroup)
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("... is sub group");
}
Group child = lookup.get("GROUP_" + id);
if (child == null)
{
throw new ExportSourceImporterException("Failed to find child group " + id);
}
if (rootGroups.contains(child))
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("... Primary created from "
+ group.gid + " to " + child.gid);
}
group.children.add(child);
rootGroups.remove(child);
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("... Secondary created from "
+ group.gid + " to " + child.gid);
}
secondaryLinks.add(new SecondaryLink(group.gid, child.gid));
}
}
else
{
if (s_logger.isDebugEnabled())
{
s_logger.debug("... is member");
}
group.members.add(id);
}
}
}
}
}
if (s_logger.isDebugEnabled())
{
s_logger.debug("Top " + rootGroups.size());
s_logger.debug("Secondary " + secondaryLinks.size());
}
}
catch (NamingException e)
{
throw new ExportSourceImporterException("Failed to import people.", e);
}
finally
{
if (ctx != null)
{
try
{
ctx.close();
}
catch (NamingException e)
{
throw new ExportSourceImporterException("Failed to import people.", e);
}
}
}
}
private static class Group
{
String gid;
String guid = GUID.generate();
HashSet<Group> children = new HashSet<Group>();
HashSet<String> members = new HashSet<String>();
HashSet<String> distinguishedNames = new HashSet<String>();
private Group(String gid)
{
this.gid = "GROUP_" + gid;
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof Group))
{
return false;
}
Group g = (Group) o;
return this.gid.equals(g.gid);
}
@Override
public int hashCode()
{
return gid.hashCode();
}
}
private static class SecondaryLink
{
String from;
String to;
private SecondaryLink(String from, String to)
{
this.from = from;
this.to = to;
}
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof Group))
{
return false;
}
SecondaryLink l = (SecondaryLink) o;
return EqualsHelper.nullSafeEquals(this.from, l.from) && EqualsHelper.nullSafeEquals(this.to, l.to);
}
@Override
public int hashCode()
{
int hashCode = 0;
if (from != null)
{
hashCode = hashCode * 37 + from.hashCode();
}
if (to != null)
{
hashCode = hashCode * 37 + to.hashCode();
}
return hashCode;
}
}
public static void main(String[] args) throws IOException
{
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
ExportSource source = (ExportSource) ctx.getBean("ldapGroupExportSource");
File file = new File(args[0]);
Writer writer = new BufferedWriter(new FileWriter(file));
XMLWriter xmlWriter = createXMLExporter(writer);
source.generateExport(xmlWriter);
xmlWriter.close();
}
private static XMLWriter createXMLExporter(Writer writer)
{
// Define output format
OutputFormat format = OutputFormat.createPrettyPrint();
format.setNewLineAfterDeclaration(false);
format.setIndentSize(3);
format.setEncoding("UTF-8");
// Construct an XML Exporter
XMLWriter xmlWriter = new XMLWriter(writer, format);
return xmlWriter;
}
public void afterPropertiesSet() throws Exception
{
viewRef = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "reference", namespaceService);
viewId = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "id", namespaceService);
viewIdRef = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "idref", namespaceService);
viewAssociations = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "associations", namespaceService);
childQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "childName", namespaceService);
viewValueQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "value", namespaceService);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ldap;
import java.util.Map;
import javax.naming.directory.InitialDirContext;
import org.alfresco.repo.security.authentication.AuthenticationException;
/**
* Interface that defines a factory for obtaining ldap directory contexts.
*
* @author Andy Hind
*/
public interface LDAPInitialDirContextFactory
{
/**
* Set the LDAP environment Hashtable properties used ot initialise the LDAP connection.
*
* @param environment
*/
public void setInitialDirContextEnvironment(Map<String, String> environment);
/**
* Use the environment properties and connect to the LDAP server.
* Used to obtain read only access to the LDAP server.
*
* @return
* @throws AuthenticationException
*/
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException;
/**
* Augment the connection environment with the identity and credentials and bind to the ldap server.
* Mainly used to validate a user's credentials during authentication.
*
* @param principal
* @param credentials
* @return
* @throws AuthenticationException
*/
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException;
}

View File

@@ -0,0 +1,197 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ldap;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.InitialDirContext;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
public class LDAPInitialDirContextFactoryImpl implements LDAPInitialDirContextFactory
{
private Map<String, String> initialDirContextEnvironment = Collections.<String, String> emptyMap();
static
{
System.setProperty("javax.security.auth.useSubjectCredentialsOnly", "false");
}
public LDAPInitialDirContextFactoryImpl()
{
super();
}
public void setInitialDirContextEnvironment(Map<String, String> initialDirContextEnvironment)
{
this.initialDirContextEnvironment = initialDirContextEnvironment;
}
public Map<String, String> getInitialDirContextEnvironment()
{
return initialDirContextEnvironment;
}
public InitialDirContext getDefaultIntialDirContext() throws AuthenticationException
{
Hashtable<String, String> env = new Hashtable<String, String>(initialDirContextEnvironment.size());
env.putAll(initialDirContextEnvironment);
env.put("javax.security.auth.useSubjectCredsOnly", "false");
return buildInitialDirContext(env);
}
private InitialDirContext buildInitialDirContext(Hashtable<String, String> env) throws AuthenticationException
{
try
{
return new InitialDirContext(env);
}
catch (javax.naming.AuthenticationException ax)
{
throw new AuthenticationException("LDAP authentication failed.", ax);
}
catch (NamingException nx)
{
throw new AuthenticationException("Unable to connect to LDAP Server; check LDAP configuration", nx);
}
}
public InitialDirContext getInitialDirContext(String principal, String credentials) throws AuthenticationException
{
if (principal == null)
{
throw new AuthenticationException("Null user name provided.");
}
if (credentials == null)
{
throw new AuthenticationException("No credentials provided.");
}
Hashtable<String, String> env = new Hashtable<String, String>(initialDirContextEnvironment.size());
env.putAll(initialDirContextEnvironment);
env.put(Context.SECURITY_PRINCIPAL, principal);
env.put(Context.SECURITY_CREDENTIALS, credentials);
return buildInitialDirContext(env);
}
public static void main(String[] args)
{
// ....build a pyramid selling scheme .....
// A group has three user members and 2 group members .... and off we go ....
// We make the people and groups to represent this and stick them into LDAP ...used to populate a test data base for user and groups
int userMembers = Integer.parseInt(args[3]);
ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext();
LDAPInitialDirContextFactory factory = (LDAPInitialDirContextFactory) applicationContext
.getBean("ldapInitialDirContextFactory");
InitialDirContext ctx = null;
try
{
ctx = factory.getInitialDirContext("cn=" + args[0] + "," + args[2], args[1]);
/* Values we'll use in creating the entry */
Attribute objClasses = new BasicAttribute("objectclass");
objClasses.add("top");
objClasses.add("person");
objClasses.add("organizationalPerson");
objClasses.add("inetOrgPerson");
for (int i = 0; i < userMembers; i++)
{
Attribute cn = new BasicAttribute("cn", "User" + i + " TestUser");
Attribute sn = new BasicAttribute("sn", "TestUser");
Attribute givenNames = new BasicAttribute("givenName", "User" + i);
Attribute telephoneNumber = new BasicAttribute("telephoneNumber", "123");
Attribute uid = new BasicAttribute("uid", "User" + i);
Attribute mail = new BasicAttribute("mail", "woof@woof");
Attribute o = new BasicAttribute("o", "Alfresco");
Attribute userPassword = new BasicAttribute("userPassword", "bobbins");
/* Specify the DN we're adding */
String dn = "cn=User" + i + " TestUser," + args[2];
Attributes orig = new BasicAttributes();
orig.put(objClasses);
orig.put(cn);
orig.put(sn);
orig.put(givenNames);
orig.put(telephoneNumber);
orig.put(uid);
orig.put(mail);
orig.put(o);
orig.put(userPassword);
try
{
ctx.destroySubcontext(dn);
}
catch (NamingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
ctx.createSubcontext(dn, orig);
}
}
catch (NamingException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
if (ctx != null)
{
try
{
ctx.close();
}
catch (NamingException e)
{
e.printStackTrace();
}
}
}
}
}

View File

@@ -0,0 +1,328 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ldap;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Map;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.importer.ExportSource;
import org.alfresco.repo.importer.ExportSourceImporterException;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ApplicationContextHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.springframework.context.ApplicationContext;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
public class LDAPPersonExportSource implements ExportSource
{
private static Log s_logger = LogFactory.getLog(LDAPPersonExportSource.class);
private String personQuery = "(objectclass=inetOrgPerson)";
private String searchBase;
private String userIdAttributeName;
private LDAPInitialDirContextFactory ldapInitialContextFactory;
private PersonService personService;
private Map<String, String> attributeMapping;
private NamespaceService namespaceService;
private String defaultHomeFolder;
public LDAPPersonExportSource()
{
super();
}
public void setPersonQuery(String personQuery)
{
this.personQuery = personQuery;
}
public void setSearchBase(String searchBase)
{
this.searchBase = searchBase;
}
public void setUserIdAttributeName(String userIdAttributeName)
{
this.userIdAttributeName = userIdAttributeName;
}
public void setLDAPInitialDirContextFactory(LDAPInitialDirContextFactory ldapInitialDirContextFactory)
{
this.ldapInitialContextFactory = ldapInitialDirContextFactory;
}
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
public void setDefaultHomeFolder(String defaultHomeFolder)
{
this.defaultHomeFolder = defaultHomeFolder;
}
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
public void setAttributeMapping(Map<String, String> attributeMapping)
{
this.attributeMapping = attributeMapping;
}
public void generateExport(XMLWriter writer)
{
QName nodeUUID = QName.createQName("sys:node-uuid", namespaceService);
Collection<String> prefixes = namespaceService.getPrefixes();
QName childQName = QName.createQName(NamespaceService.REPOSITORY_VIEW_PREFIX, "childName", namespaceService);
try
{
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_1_0_URI, childQName.getLocalName(), childQName
.toPrefixString(), null, ContentModel.TYPE_PERSON.toPrefixString(namespaceService));
writer.startDocument();
for (String prefix : prefixes)
{
if (!prefix.equals("xml"))
{
String uri = namespaceService.getNamespaceURI(prefix);
writer.startPrefixMapping(prefix, uri);
}
}
writer.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view",
NamespaceService.REPOSITORY_VIEW_PREFIX + ":" + "view", new AttributesImpl());
InitialDirContext ctx = null;
try
{
ctx = ldapInitialContextFactory.getDefaultIntialDirContext();
// Authentication has been successful.
// Set the current user, they are now authenticated.
SearchControls userSearchCtls = new SearchControls();
userSearchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
System.out.println("COUNT "+userSearchCtls.getCountLimit());
System.out.println("TIME "+userSearchCtls.getTimeLimit());
userSearchCtls.setCountLimit(Integer.MAX_VALUE);
NamingEnumeration searchResults = ctx.search(searchBase, personQuery, userSearchCtls);
while (searchResults.hasMoreElements())
{
SearchResult result = (SearchResult) searchResults.next();
Attributes attributes = result.getAttributes();
Attribute uidAttribute = attributes.get(userIdAttributeName);
String uid = (String) uidAttribute.get(0);
if(s_logger.isDebugEnabled())
{
s_logger.debug("Adding user for "+uid);
}
System.out.println("User "+uid);
writer.startElement(ContentModel.TYPE_PERSON.getNamespaceURI(), ContentModel.TYPE_PERSON
.getLocalName(), ContentModel.TYPE_PERSON.toPrefixString(namespaceService), attrs);
// permissions
// owner
writer.startElement(ContentModel.ASPECT_OWNABLE.getNamespaceURI(), ContentModel.ASPECT_OWNABLE
.getLocalName(), ContentModel.ASPECT_OWNABLE.toPrefixString(namespaceService),
new AttributesImpl());
writer.endElement(ContentModel.ASPECT_OWNABLE.getNamespaceURI(), ContentModel.ASPECT_OWNABLE
.getLocalName(), ContentModel.ASPECT_OWNABLE.toPrefixString(namespaceService));
writer.startElement(ContentModel.PROP_OWNER.getNamespaceURI(), ContentModel.PROP_OWNER
.getLocalName(), ContentModel.PROP_OWNER.toPrefixString(namespaceService),
new AttributesImpl());
writer.characters(uid.toCharArray(), 0, uid.length());
writer.endElement(ContentModel.PROP_OWNER.getNamespaceURI(),
ContentModel.PROP_OWNER.getLocalName(), ContentModel.PROP_OWNER
.toPrefixString(namespaceService));
for (String key : attributeMapping.keySet())
{
QName keyQName = QName.createQName(key, namespaceService);
writer.startElement(keyQName.getNamespaceURI(), keyQName.getLocalName(), keyQName
.toPrefixString(namespaceService), new AttributesImpl());
// cater for null
String attribute = attributeMapping.get(key);
if (attribute != null)
{
String value = (String) attributes.get(attribute).get(0);
if (value != null)
{
writer.characters(value.toCharArray(), 0, value.length());
}
}
writer.endElement(keyQName.getNamespaceURI(), keyQName.getLocalName(), keyQName
.toPrefixString(namespaceService));
}
// Default home folder
if (!(attributeMapping.keySet().contains(ContentModel.PROP_HOMEFOLDER.toString()) || attributeMapping
.keySet().contains(ContentModel.PROP_HOMEFOLDER.toPrefixString(namespaceService))))
{
// Only if we are creating the person for the first time
if (!personService.personExists(uid))
{
writer.startElement(ContentModel.PROP_HOMEFOLDER.getNamespaceURI(),
ContentModel.PROP_HOMEFOLDER.getLocalName(), ContentModel.PROP_HOMEFOLDER
.toPrefixString(namespaceService), new AttributesImpl());
if (defaultHomeFolder != null)
{
writer.characters(defaultHomeFolder.toCharArray(), 0, defaultHomeFolder.length());
}
writer.endElement(ContentModel.PROP_HOMEFOLDER.getNamespaceURI(),
ContentModel.PROP_HOMEFOLDER.getLocalName(), ContentModel.PROP_HOMEFOLDER
.toPrefixString(namespaceService));
}
}
if (personService.personExists(uid))
{
String uguid = personService.getPerson(uid).getId();
writer.startElement(nodeUUID.getNamespaceURI(), nodeUUID.getLocalName(), nodeUUID
.toPrefixString(namespaceService), new AttributesImpl());
writer.characters(uguid.toCharArray(), 0, uguid.length());
writer.endElement(nodeUUID.getNamespaceURI(), nodeUUID.getLocalName(), nodeUUID
.toPrefixString(namespaceService));
}
writer.endElement(ContentModel.TYPE_PERSON.getNamespaceURI(), ContentModel.TYPE_PERSON
.getLocalName(), ContentModel.TYPE_PERSON.toPrefixString(namespaceService));
}
}
catch (NamingException e)
{
throw new ExportSourceImporterException("Failed to import people.", e);
}
finally
{
if (ctx != null)
{
try
{
ctx.close();
}
catch (NamingException e)
{
throw new ExportSourceImporterException("Failed to import people.", e);
}
}
}
for (String prefix : prefixes)
{
if (!prefix.equals("xml"))
{
writer.endPrefixMapping(prefix);
}
}
writer.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, "view", NamespaceService.REPOSITORY_VIEW_PREFIX
+ ":" + "view");
writer.endDocument();
}
catch (SAXException e)
{
throw new ExportSourceImporterException("Failed to create file for import.", e);
}
}
public static void main(String[] args) throws IOException
{
ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
ExportSource source = (ExportSource) ctx.getBean("ldapPeopleExportSource");
File file = new File(args[0]);
Writer writer = new BufferedWriter(new FileWriter(file));
XMLWriter xmlWriter = createXMLExporter(writer);
source.generateExport(xmlWriter);
xmlWriter.close();
}
private static XMLWriter createXMLExporter(Writer writer)
{
// Define output format
OutputFormat format = OutputFormat.createPrettyPrint();
format.setNewLineAfterDeclaration(false);
format.setIndentSize(3);
format.setEncoding("UTF-8");
// Construct an XML Exporter
XMLWriter xmlWriter = new XMLWriter(writer, format);
return xmlWriter;
}
}

View File

@@ -0,0 +1,932 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ntlm;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.Enumeration;
import java.util.Hashtable;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationServiceException;
import net.sf.acegisecurity.BadCredentialsException;
import net.sf.acegisecurity.CredentialsExpiredException;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.GrantedAuthorityImpl;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.server.auth.PasswordEncryptor;
import org.alfresco.filesys.server.auth.passthru.AuthenticateSession;
import org.alfresco.filesys.server.auth.passthru.PassthruServers;
import org.alfresco.filesys.smb.SMBException;
import org.alfresco.filesys.smb.SMBStatus;
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.NTLMMode;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PersonService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* NTLM Authentication Component Class
*
* <p>Provides authentication using passthru to a Windows server(s)/domain controller(s) using the accounts
* defined on the passthru server to validate users.
*
* @author GKSpencer
*/
public class NTLMAuthenticationComponentImpl extends AbstractAuthenticationComponent
{
// Logging
private static final Log logger = LogFactory.getLog("org.alfresco.passthru.auth");
// Constants
//
// Standard authorities
public static final String NTLMAuthorityGuest = "Guest";
public static final String NTLMAuthorityAdministrator = "Administrator";
// Active session timeout
private static final long DefaultSessionTimeout = 60000L; // 1 minute
private static final long MinimumSessionTimeout = 5000L; // 5 seconds
// Passthru authentication servers
private PassthruServers m_passthruServers;
// Password encryptor for generating password hash for local authentication
private PasswordEncryptor m_encryptor;
// Allow guest access
private boolean m_allowGuest;
// Table of currently active passthru authentications and the associated authentication session
//
// If the two authentication stages are not completed within a reasonable time the authentication
// session will be closed by the reaper thread.
private Hashtable<NTLMPassthruToken,AuthenticateSession> m_passthruSessions;
// Active authentication session timeout, in milliseconds
private long m_passthruSessTmo = DefaultSessionTimeout;
// Authentication session reaper thread
private PassthruReaperThread m_reaperThread;
// Person service, used to map passthru usernames to Alfresco person names
private PersonService m_personService;
private NodeService m_nodeService;
/**
* Passthru Session Reaper Thread
*/
class PassthruReaperThread extends Thread
{
// Thread shutdown request flag
private boolean m_ishutdown;
// Reaper wakeup interval, in milliseconds
private long m_wakeupInterval = m_passthruSessTmo / 2;
/**
* Default constructor
*/
PassthruReaperThread()
{
setDaemon(true);
setName("PassthruReaper");
start();
}
/**
* Set the wakeup interval
*
* @param wakeup long
*/
public final void setWakeup(long wakeup)
{
m_wakeupInterval = wakeup;
}
/**
* Main thread code
*/
public void run()
{
// Loop until shutdown
m_ishutdown = false;
while ( m_ishutdown == false)
{
// Sleep for a while
try
{
sleep( m_wakeupInterval);
}
catch ( InterruptedException ex)
{
}
// Check if there are any active sessions to check
if ( m_passthruSessions.size() > 0)
{
// Enumerate the active sessions
Enumeration<NTLMPassthruToken> tokenEnum = m_passthruSessions.keys();
long timeNow = System.currentTimeMillis();
while (tokenEnum.hasMoreElements())
{
// Get the current NTLM token and check if it has expired
NTLMPassthruToken ntlmToken = tokenEnum.nextElement();
if ( ntlmToken != null && ntlmToken.getAuthenticationExpireTime() < timeNow)
{
// Authentication token has expired, close the associated authentication session
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
if ( authSess != null)
{
try
{
// Close the authentication session
authSess.CloseSession();
}
catch ( Exception ex)
{
// Debug
if(logger.isDebugEnabled())
logger.debug("Error closing expired authentication session", ex);
}
}
// Remove the expired token from the active list
m_passthruSessions.remove(ntlmToken);
// Debug
if(logger.isDebugEnabled())
logger.debug("Removed expired NTLM token " + ntlmToken);
}
}
}
}
// Debug
if(logger.isDebugEnabled())
logger.debug("Passthru reaper thread shutdown");
}
/**
* Shutdown the reaper thread
*/
public final void shutdownRequest()
{
m_ishutdown = true;
this.interrupt();
}
}
/**
* Class constructor
*/
public NTLMAuthenticationComponentImpl() {
// Create the passthru authentication server list
m_passthruServers = new PassthruServers();
// Create the password encryptor for local password hashing
m_encryptor = new PasswordEncryptor();
// Create the active session list and reaper thread
m_passthruSessions = new Hashtable<NTLMPassthruToken,AuthenticateSession>();
m_reaperThread = new PassthruReaperThread();
}
/**
* Determine if guest logons are allowed
*
* @return boolean
*/
public final boolean allowsGuest()
{
return m_allowGuest;
}
/**
* Set the domain to authenticate against
*
* @param domain String
*/
public void setDomain(String domain) {
// Check if the passthru server list is already configured
if ( m_passthruServers.getTotalServerCount() > 0)
throw new AlfrescoRuntimeException("Passthru server list already configured");
// Configure the passthru authentication server list using the domain controllers
m_passthruServers.setDomain(domain);
}
/**
* Set the server(s) to authenticate against
*
* @param servers String
*/
public void setServers(String servers) {
// Check if the passthru server list is already configured
if ( m_passthruServers.getTotalServerCount() > 0)
throw new AlfrescoRuntimeException("Passthru server list already configured");
// Configure the passthru authenticaiton list using a list of server names/addresses
m_passthruServers.setServerList(servers);
}
/**
* Use the local server as the authentication server
*
* @param useLocal String
*/
public void setUseLocalServer(String useLocal)
{
// Check if the local server should be used for authentication
if ( Boolean.parseBoolean(useLocal) == true)
{
// Check if the passthru server list is already configured
if ( m_passthruServers.getTotalServerCount() > 0)
throw new AlfrescoRuntimeException("Passthru server list already configured");
try
{
// Get the list of local network addresses
InetAddress[] localAddrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
// Build the list of local addresses
if ( localAddrs != null && localAddrs.length > 0)
{
StringBuilder addrStr = new StringBuilder();
for ( InetAddress curAddr : localAddrs)
{
if ( curAddr.isLoopbackAddress() == false)
{
addrStr.append(curAddr.getHostAddress());
addrStr.append(",");
}
}
if ( addrStr.length() > 0)
addrStr.setLength(addrStr.length() - 1);
// Set the server list using the local address list
m_passthruServers.setServerList(addrStr.toString());
}
else
throw new AlfrescoRuntimeException("No local server address(es)");
}
catch ( UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Failed to get local address list");
}
}
}
/**
* Allow guest access
*
* @param guest String
*/
public void setGuestAccess(String guest)
{
m_allowGuest = Boolean.parseBoolean(guest);
}
/**
* Set the JCE provider
*
* @param providerClass String
*/
public void setJCEProvider(String providerClass)
{
// Set the JCE provider, required to provide various encryption/hashing algorithms not available
// in the standard Sun JDK/JRE
try
{
// Load the JCE provider class and validate
Object jceObj = Class.forName(providerClass).newInstance();
if (jceObj instanceof java.security.Provider)
{
// Inform listeners, validate the configuration change
Provider jceProvider = (Provider) jceObj;
// Add the JCE provider
Security.addProvider(jceProvider);
// Debug
if ( logger.isDebugEnabled())
logger.debug("Using JCE provider " + providerClass);
}
else
{
throw new AlfrescoRuntimeException("JCE provider class is not a valid Provider class");
}
}
catch (ClassNotFoundException ex)
{
throw new AlfrescoRuntimeException("JCE provider class " + providerClass + " not found");
}
catch (Exception ex)
{
throw new AlfrescoRuntimeException("JCE provider class error", ex);
}
}
/**
* Set the authentication session timeout, in seconds
*
* @param sessTmo String
*/
public void setSessionTimeout(String sessTmo)
{
// Convert to an integer value and range check the timeout value
try
{
// Convert to an integer value
long sessTmoMilli = Long.parseLong(sessTmo) * 1000L;
if ( sessTmoMilli < MinimumSessionTimeout)
throw new AlfrescoRuntimeException("Authentication session timeout too low, " + sessTmo);
// Set the authentication session timeout value
m_passthruSessTmo = sessTmoMilli;
// Set the reaper thread wakeup interval
m_reaperThread.setWakeup( sessTmoMilli / 2);
}
catch(NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid authenication session timeout value");
}
}
/**
* Set the person service
*
* @param personService PersonService
*/
public final void setPersonService(PersonService personService)
{
m_personService = personService;
}
/**
* Set the node service
*
* @param nodeService NodeService
*/
public final void setNodeService(NodeService nodeService)
{
m_nodeService = nodeService;
}
/**
* Return the authentication session timeout, in milliseconds
*
* @return long
*/
private final long getSessionTimeout()
{
return m_passthruSessTmo;
}
/**
* Authenticate
*
* @param userName String
* @param password char[]
* @throws AuthenticationException
*/
public void authenticate(String userName, char[] password) throws AuthenticationException
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Authenticate user=" + userName + " via local credentials");
// Create a local authentication token
NTLMLocalToken authToken = new NTLMLocalToken(userName, new String(password));
// Authenticate using the token
authenticate( authToken);
setCurrentUser( userName.toLowerCase());
}
/**
* Authenticate using a token
*
* @param token Authentication
* @return Authentication
* @throws AuthenticationException
*/
public Authentication authenticate(Authentication auth) throws AuthenticationException
{
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Authenticate " + auth + " via token");
// Check if the token is for passthru authentication
if( auth instanceof NTLMPassthruToken)
{
// Access the NTLM passthru token
NTLMPassthruToken ntlmToken = (NTLMPassthruToken) auth;
// Authenticate using passthru
authenticatePassthru(ntlmToken);
}
// Check for a local authentication token
else if( auth instanceof NTLMLocalToken)
{
AuthenticateSession authSess = null;
try
{
// Access the NTLM token
NTLMLocalToken ntlmToken = (NTLMLocalToken) auth;
// Open a session to an authentication server
authSess = m_passthruServers.openSession();
// Authenticate using the credentials supplied
authenticateLocal(ntlmToken, authSess);
}
finally
{
// Make sure the authentication session is closed
if ( authSess != null)
{
try
{
authSess.CloseSession();
}
catch ( Exception ex)
{
}
}
}
}
else
{
// Unsupported authentication token
throw new AuthenticationException("Unsupported authentication token type");
}
// Return the updated authentication token
return getCurrentAuthentication();
}
/**
* Get the enum that describes NTLM integration
*
* @return NTLMMode
*/
public NTLMMode getNTLMMode()
{
return NTLMMode.PASS_THROUGH;
}
/**
* Get the MD4 password hash, as required by NTLM based authentication methods.
*
* @param userName String
* @return String
*/
public String getMD4HashedPassword(String userName)
{
// Do not support MD4 hashed password
throw new AlfrescoRuntimeException("MD4 passwords not supported");
}
/**
* Authenticate a user using local credentials
*
* @param ntlmToken NTLMLocalToken
* @param authSess AuthenticateSession
*/
private void authenticateLocal(NTLMLocalToken ntlmToken, AuthenticateSession authSess)
{
try
{
// Get the plaintext password and generate an NTLM1 password hash
String username = (String) ntlmToken.getPrincipal();
String plainPwd = (String) ntlmToken.getCredentials();
byte[] ntlm1Pwd = m_encryptor.generateEncryptedPassword( plainPwd, authSess.getEncryptionKey(), PasswordEncryptor.NTLM1);
// Send the logon request to the authentication server
//
// Note: Only use the stronger NTLM hash, we do not send the LM hash
authSess.doSessionSetup(username, null, ntlm1Pwd);
// Check if the session has logged on as a guest
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
{
// If guest access is enabled add a guest authority to the token
if ( allowsGuest())
{
// Set the guest authority
GrantedAuthority[] authorities = new GrantedAuthority[2];
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
authorities[1] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
ntlmToken.setAuthorities(authorities);
}
else
{
// Guest access not allowed
throw new AuthenticationException("Guest logons disabled");
}
}
else
{
// Set authorities
GrantedAuthority[] authorities = new GrantedAuthority[1];
authorities[0] = new GrantedAuthorityImpl("ROLE_AUTHENTICATED");
ntlmToken.setAuthorities(authorities);
}
// Indicate that the token is authenticated
ntlmToken.setAuthenticated(true);
// Map the passthru username to an Alfresco person
NodeRef userNode = m_personService.getPerson(username);
if ( userNode != null)
{
// Get the person name and use that as the current user to line up with permission checks
String personName = (String) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
setCurrentUser(personName);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Setting current user using person " + personName + " (username " + username + ")");
}
else
{
// Set using the user name, lowercase the name if hte person service is case insensitive
if ( m_personService.getUserNamesAreCaseSensitive() == false)
username = username.toLowerCase();
setCurrentUser( username);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Setting current user using username " + username);
}
// Debug
if ( logger.isDebugEnabled())
logger.debug("Authenticated token=" + ntlmToken);
}
catch (NoSuchAlgorithmException ex)
{
// JCE provider does not have the required encryption/hashing algorithms
throw new AuthenticationServiceException("JCE provider error", ex);
}
catch (IOException ex)
{
// Error connecting to the authentication server
throw new AuthenticationServiceException("I/O error", ex);
}
catch (SMBException ex)
{
// Check the returned status code to determine why the logon failed and throw an appropriate exception
if ( ex.getErrorClass() == SMBStatus.NTErr)
{
AuthenticationException authEx = null;
switch( ex.getErrorCode())
{
case SMBStatus.NTLogonFailure:
authEx = new AuthenticationException("Logon failure");
break;
case SMBStatus.NTAccountDisabled:
authEx = new AuthenticationException("Account disabled");
break;
default:
authEx = new AuthenticationException("Logon failure");
break;
}
throw authEx;
}
else
throw new AuthenticationException("Logon failure");
}
}
/**
* Authenticate using passthru authentication with a client
*
* @param ntlmToken NTLMPassthruToken
*/
private void authenticatePassthru(NTLMPassthruToken ntlmToken)
{
// Check if the token has an authentication session, if not then it is either a new token
// or the session has been timed out
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
if ( authSess == null)
{
// Check if the token has a challenge, if it does then the associated session has been
// timed out
if ( ntlmToken.getChallenge() != null)
throw new CredentialsExpiredException("Authentication session expired");
// Open an authentication session for the new token and add to the active session list
authSess = m_passthruServers.openSession();
ntlmToken.setAuthenticationExpireTime(System.currentTimeMillis() + getSessionTimeout());
// Get the challenge from the initial session negotiate stage
ntlmToken.setChallenge(new NTLMChallenge(authSess.getEncryptionKey()));
StringBuilder details = new StringBuilder();
// Build a details string with the authentication session details
details.append(authSess.getDomain());
details.append("\\");
details.append(authSess.getPCShare().getNodeName());
details.append(",");
details.append(authSess.getSession().getProtocolName());
ntlmToken.setDetails(details.toString());
// Put the token/session into the active session list
m_passthruSessions.put(ntlmToken, authSess);
// Debug
if ( logger.isDebugEnabled())
logger.debug("Passthru stage 1 token " + ntlmToken);
}
else
{
try
{
// Stage two of the authentication, send the hashed password to the authentication server
byte[] lmPwd = null;
byte[] ntlmPwd = null;
if ( ntlmToken.getPasswordType() == PasswordEncryptor.LANMAN)
lmPwd = ntlmToken.getHashedPassword();
else if ( ntlmToken.getPasswordType() == PasswordEncryptor.NTLM1)
ntlmPwd = ntlmToken.getHashedPassword();
String username = (String) ntlmToken.getPrincipal();
authSess.doSessionSetup(username, lmPwd, ntlmPwd);
// Check if the session has logged on as a guest
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
{
// If guest access is enabled add a guest authority to the token
if ( allowsGuest())
{
// Set the guest authority
GrantedAuthority[] authorities = new GrantedAuthority[1];
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
ntlmToken.setAuthorities(authorities);
}
else
{
// Guest access not allowed
throw new BadCredentialsException("Guest logons disabled");
}
}
// Indicate that the token is authenticated
ntlmToken.setAuthenticated(true);
// Map the passthru username to an Alfresco person
NodeRef userNode = m_personService.getPerson(username);
if ( userNode != null)
{
// Get the person name and use that as the current user to line up with permission checks
String personName = (String) m_nodeService.getProperty(userNode, ContentModel.PROP_USERNAME);
setCurrentUser(personName);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Setting current user using person " + personName + " (username " + username + ")");
}
else
{
// Set using the user name, lowercase the name if the person service is case insensitive
if ( m_personService.getUserNamesAreCaseSensitive() == false)
username = username.toLowerCase();
setCurrentUser( username);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Setting current user using username " + username);
}
}
catch (IOException ex)
{
// Error connecting to the authentication server
throw new AuthenticationServiceException("I/O error", ex);
}
catch (SMBException ex)
{
// Debug
if ( logger.isDebugEnabled())
logger.debug("Passthru exception, " + ex);
// Check the returned status code to determine why the logon failed and throw an appropriate exception
if ( ex.getErrorClass() == SMBStatus.NTErr)
{
AuthenticationException authEx = null;
switch( ex.getErrorCode())
{
case SMBStatus.NTLogonFailure:
authEx = new AuthenticationException("Logon failure");
break;
case SMBStatus.NTAccountDisabled:
authEx = new AuthenticationException("Account disabled");
break;
default:
authEx = new AuthenticationException("Logon failure");
break;
}
throw authEx;
}
else
throw new BadCredentialsException("Logon failure");
}
finally
{
// Make sure the authentication session is closed
if ( authSess != null)
{
try
{
// Remove the session from the active list
m_passthruSessions.remove(ntlmToken);
// Close the session to the authentication server
authSess.CloseSession();
}
catch (Exception ex)
{
}
}
}
}
}
/**
* Check if the user exists
*
* @param userName String
* @return boolean
*/
public boolean exists(String userName)
{
throw new UnsupportedOperationException();
}
@Override
protected boolean implementationAllowsGuestLogin()
{
return allowsGuest();
}
}

View File

@@ -0,0 +1,755 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ntlm;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.Enumeration;
import java.util.Hashtable;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.filesys.server.auth.PasswordEncryptor;
import org.alfresco.filesys.server.auth.passthru.AuthenticateSession;
import org.alfresco.filesys.server.auth.passthru.PassthruServers;
import org.alfresco.filesys.smb.SMBException;
import org.alfresco.filesys.smb.SMBStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.acegisecurity.*;
import net.sf.acegisecurity.providers.*;
/**
* NTLM Authentication Provider
*
* @author GKSpencer
*/
public class NTLMAuthenticationProvider implements AuthenticationProvider
{
private static final Log logger = LogFactory.getLog("org.alfresco.acegi");
// Constants
//
// Standard authorities
public static final String NTLMAuthorityGuest = "Guest";
public static final String NTLMAuthorityAdministrator = "Administrator";
// Active session timeout
private static final long DefaultSessionTimeout = 60000L; // 1 minute
private static final long MinimumSessionTimeout = 5000L; // 5 seconds
// Passthru authentication servers
private PassthruServers m_passthruServers;
// Password encryptor for generating password hash for local authentication
private PasswordEncryptor m_encryptor;
// Allow guest access
private boolean m_allowGuest;
// Table of currently active passthru authentications and the associated authentication session
//
// If the two authentication stages are not completed within a reasonable time the authentication
// session will be closed by the reaper thread.
private Hashtable<NTLMPassthruToken,AuthenticateSession> m_passthruSessions;
// Active authentication session timeout, in milliseconds
private long m_passthruSessTmo = DefaultSessionTimeout;
// Authentication session reaper thread
private PassthruReaperThread m_reaperThread;
/**
* Passthru Session Repear Thread
*/
class PassthruReaperThread extends Thread
{
// Thread shutdown request flag
private boolean m_ishutdown;
// Reaper wakeup interval, in milliseconds
private long m_wakeupInterval = m_passthruSessTmo / 2;
/**
* Default constructor
*/
PassthruReaperThread()
{
setDaemon(true);
setName("PassthruReaper");
start();
}
/**
* Set the wakeup interval
*
* @param wakeup long
*/
public final void setWakeup(long wakeup)
{
m_wakeupInterval = wakeup;
}
/**
* Main thread code
*/
public void run()
{
// Loop until shutdown
m_ishutdown = false;
while ( m_ishutdown == false)
{
// Sleep for a while
try
{
sleep( m_wakeupInterval);
}
catch ( InterruptedException ex)
{
}
// Check if there are any active sessions to check
if ( m_passthruSessions.size() > 0)
{
// Enumerate the active sessions
Enumeration<NTLMPassthruToken> tokenEnum = m_passthruSessions.keys();
long timeNow = System.currentTimeMillis();
while (tokenEnum.hasMoreElements())
{
// Get the current NTLM token and check if it has expired
NTLMPassthruToken ntlmToken = tokenEnum.nextElement();
if ( ntlmToken != null && ntlmToken.getAuthenticationExpireTime() < timeNow)
{
// Authentication token has expired, close the associated authentication session
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
if ( authSess != null)
{
try
{
// Close the authentication session
authSess.CloseSession();
}
catch ( Exception ex)
{
// Debug
if(logger.isDebugEnabled())
logger.debug("Error closing expired authentication session", ex);
}
}
// Remove the expired token from the active list
m_passthruSessions.remove(ntlmToken);
// Debug
if(logger.isDebugEnabled())
logger.debug("Removed expired NTLM token " + ntlmToken);
}
}
}
}
// Debug
if(logger.isDebugEnabled())
logger.debug("Passthru reaper thread shutdown");
}
/**
* Shutdown the reaper thread
*/
public final void shutdownRequest()
{
m_ishutdown = true;
this.interrupt();
}
}
/**
* Class constructor
*/
public NTLMAuthenticationProvider() {
// Create the passthru authentication server list
m_passthruServers = new PassthruServers();
// Create the password encryptor for local password hashing
m_encryptor = new PasswordEncryptor();
// Create the active session list and reaper thread
m_passthruSessions = new Hashtable<NTLMPassthruToken,AuthenticateSession>();
m_reaperThread = new PassthruReaperThread();
}
/**
* Authenticate a user
*
* @param auth Authentication
* @return Authentication
* @exception AuthenticationException
*/
public Authentication authenticate(Authentication auth) throws AuthenticationException
{
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Authenticate " + auth);
// Check if the token is for passthru authentication
if( auth instanceof NTLMPassthruToken)
{
// Access the NTLM passthru token
NTLMPassthruToken ntlmToken = (NTLMPassthruToken) auth;
// Authenticate using passthru
authenticatePassthru(ntlmToken);
}
// Check for a local authentication token
else if( auth instanceof NTLMLocalToken)
{
AuthenticateSession authSess = null;
try
{
// Access the NTLM token
NTLMLocalToken ntlmToken = (NTLMLocalToken) auth;
// Open a session to an authentication server
authSess = m_passthruServers.openSession();
// Authenticate using the credentials supplied
authenticateLocal(ntlmToken, authSess);
}
finally
{
// Make sure the authentication session is closed
if ( authSess != null)
{
try
{
authSess.CloseSession();
}
catch ( Exception ex)
{
}
}
}
}
// Return the updated authentication token
return auth;
}
/**
* Determine if this provider supports the specified authentication token
*
* @param authentication Class
*/
public boolean supports(Class authentication)
{
// Check if the authentication is an NTLM authentication token
if ( NTLMPassthruToken.class.isAssignableFrom(authentication))
return true;
return NTLMLocalToken.class.isAssignableFrom(authentication);
}
/**
* Determine if guest logons are allowed
*
* @return boolean
*/
public final boolean allowsGuest()
{
return m_allowGuest;
}
/**
* Set the domain to authenticate against
*
* @param domain String
*/
public final void setDomain(String domain) {
// Check if the passthru server list is already configured
if ( m_passthruServers.getTotalServerCount() > 0)
throw new AlfrescoRuntimeException("Passthru server list already configured");
// Configure the passthru authentication server list using the domain controllers
m_passthruServers.setDomain(domain);
}
/**
* Set the server(s) to authenticate against
*
* @param servers String
*/
public final void setServers(String servers) {
// Check if the passthru server list is already configured
if ( m_passthruServers.getTotalServerCount() > 0)
throw new AlfrescoRuntimeException("Passthru server list already configured");
// Configure the passthru authenticaiton list using a list of server names/addresses
m_passthruServers.setServerList(servers);
}
/**
* Use the local server as the authentication server
*
* @param useLocal String
*/
public final void setUseLocalServer(String useLocal)
{
// Check if the local server should be used for authentication
if ( Boolean.parseBoolean(useLocal) == true)
{
// Check if the passthru server list is already configured
if ( m_passthruServers.getTotalServerCount() > 0)
throw new AlfrescoRuntimeException("Passthru server list already configured");
try
{
// Get the list of local network addresses
InetAddress[] localAddrs = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
// Build the list of local addresses
if ( localAddrs != null && localAddrs.length > 0)
{
StringBuilder addrStr = new StringBuilder();
for ( InetAddress curAddr : localAddrs)
{
if ( curAddr.isLoopbackAddress() == false)
{
addrStr.append(curAddr.getHostAddress());
addrStr.append(",");
}
}
if ( addrStr.length() > 0)
addrStr.setLength(addrStr.length() - 1);
// Set the server list using the local address list
m_passthruServers.setServerList(addrStr.toString());
}
else
throw new AlfrescoRuntimeException("No local server address(es)");
}
catch ( UnknownHostException ex)
{
throw new AlfrescoRuntimeException("Failed to get local address list");
}
}
}
/**
* Allow guest access
*
* @param guest String
*/
public final void setGuestAccess(String guest)
{
m_allowGuest = Boolean.parseBoolean(guest);
}
/**
* Set the JCE provider
*
* @param providerClass String
*/
public final void setJCEProvider(String providerClass)
{
// Set the JCE provider, required to provide various encryption/hashing algorithms not available
// in the standard Sun JDK/JRE
try
{
// Load the JCE provider class and validate
Object jceObj = Class.forName(providerClass).newInstance();
if (jceObj instanceof java.security.Provider)
{
// Inform listeners, validate the configuration change
Provider jceProvider = (Provider) jceObj;
// Add the JCE provider
Security.addProvider(jceProvider);
// Debug
if ( logger.isDebugEnabled())
logger.debug("Using JCE provider " + providerClass);
}
else
{
throw new AlfrescoRuntimeException("JCE provider class is not a valid Provider class");
}
}
catch (ClassNotFoundException ex)
{
throw new AlfrescoRuntimeException("JCE provider class " + providerClass + " not found");
}
catch (Exception ex)
{
throw new AlfrescoRuntimeException("JCE provider class error", ex);
}
}
/**
* Set the authentication session timeout, in seconds
*
* @param sessTmo String
*/
public final void setSessionTimeout(String sessTmo)
{
// Convert to an integer value and range check the timeout value
try
{
// Convert to an integer value
long sessTmoMilli = Long.parseLong(sessTmo) * 1000L;
if ( sessTmoMilli < MinimumSessionTimeout)
throw new AlfrescoRuntimeException("Authentication session timeout too low, " + sessTmo);
// Set the authentication session timeout value
m_passthruSessTmo = sessTmoMilli;
// Set the reaper thread wakeup interval
m_reaperThread.setWakeup( sessTmoMilli / 2);
}
catch(NumberFormatException ex)
{
throw new AlfrescoRuntimeException("Invalid authenication session timeout value");
}
}
/**
* Return the authentication session timeout, in milliseconds
*
* @return long
*/
private final long getSessionTimeout()
{
return m_passthruSessTmo;
}
/**
* Authenticate a user using local credentials
*
* @param ntlmToken NTLMLocalToken
* @param authSess AuthenticateSession
*/
private void authenticateLocal(NTLMLocalToken ntlmToken, AuthenticateSession authSess)
{
try
{
// Get the plaintext password and generate an NTLM1 password hash
String username = (String) ntlmToken.getPrincipal();
String plainPwd = (String) ntlmToken.getCredentials();
byte[] ntlm1Pwd = m_encryptor.generateEncryptedPassword( plainPwd, authSess.getEncryptionKey(), PasswordEncryptor.NTLM1);
// Send the logon request to the authentication server
//
// Note: Only use the stronger NTLM hash, we do not send the LM hash
authSess.doSessionSetup(username, null, ntlm1Pwd);
// Check if the session has logged on as a guest
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
{
// If guest access is enabled add a guest authority to the token
if ( allowsGuest())
{
// Set the guest authority
GrantedAuthority[] authorities = new GrantedAuthority[1];
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
ntlmToken.setAuthorities(authorities);
}
else
{
// Guest access not allowed
throw new BadCredentialsException("Guest logons disabled");
}
}
// Indicate that the token is authenticated
ntlmToken.setAuthenticated(true);
}
catch (NoSuchAlgorithmException ex)
{
// JCE provider does not have the required encryption/hashing algorithms
throw new AuthenticationServiceException("JCE provider error", ex);
}
catch (IOException ex)
{
// Error connecting to the authentication server
throw new AuthenticationServiceException("I/O error", ex);
}
catch (SMBException ex)
{
// Check the returned status code to determine why the logon failed and throw an appropriate exception
if ( ex.getErrorClass() == SMBStatus.NTErr)
{
AuthenticationException authEx = null;
switch( ex.getErrorCode())
{
case SMBStatus.NTLogonFailure:
authEx = new BadCredentialsException("Logon failure");
break;
case SMBStatus.NTAccountDisabled:
authEx = new DisabledException("Account disabled");
break;
default:
authEx = new BadCredentialsException("Logon failure");
break;
}
throw authEx;
}
else
throw new BadCredentialsException("Logon failure");
}
}
/**
* Authenticate using passthru authentication with a client
*
* @param ntlmToken NTLMPassthruToken
*/
private void authenticatePassthru(NTLMPassthruToken ntlmToken)
{
// Check if the token has an authentication session, if not then it is either a new token
// or the session has been timed out
AuthenticateSession authSess = m_passthruSessions.get(ntlmToken);
if ( authSess == null)
{
// Check if the token has a challenge, if it does then the associated session has been
// timed out
if ( ntlmToken.getChallenge() != null)
throw new CredentialsExpiredException("Authentication session expired");
// Open an authentication session for the new token and add to the active session list
authSess = m_passthruServers.openSession();
ntlmToken.setAuthenticationExpireTime(System.currentTimeMillis() + getSessionTimeout());
// Get the challenge from the initial session negotiate stage
ntlmToken.setChallenge(new NTLMChallenge(authSess.getEncryptionKey()));
StringBuilder details = new StringBuilder();
// Build a details string with the authentication session details
details.append(authSess.getDomain());
details.append("\\");
details.append(authSess.getPCShare().getNodeName());
details.append(",");
details.append(authSess.getSession().getProtocolName());
ntlmToken.setDetails(details.toString());
// Put the token/session into the active session list
m_passthruSessions.put(ntlmToken, authSess);
// Debug
if ( logger.isDebugEnabled())
logger.debug("Passthru stage 1 token " + ntlmToken);
}
else
{
try
{
// Stage two of the authentication, send the hashed password to the authentication server
byte[] lmPwd = null;
byte[] ntlmPwd = null;
if ( ntlmToken.getPasswordType() == PasswordEncryptor.LANMAN)
lmPwd = ntlmToken.getHashedPassword();
else if ( ntlmToken.getPasswordType() == PasswordEncryptor.NTLM1)
ntlmPwd = ntlmToken.getHashedPassword();
String username = (String) ntlmToken.getPrincipal();
authSess.doSessionSetup(username, lmPwd, ntlmPwd);
// Check if the session has logged on as a guest
if ( authSess.isGuest() || username.equalsIgnoreCase("GUEST"))
{
// If guest access is enabled add a guest authority to the token
if ( allowsGuest())
{
// Set the guest authority
GrantedAuthority[] authorities = new GrantedAuthority[1];
authorities[0] = new GrantedAuthorityImpl(NTLMAuthorityGuest);
ntlmToken.setAuthorities(authorities);
}
else
{
// Guest access not allowed
throw new BadCredentialsException("Guest logons disabled");
}
}
// Indicate that the token is authenticated
ntlmToken.setAuthenticated(true);
}
catch (IOException ex)
{
// Error connecting to the authentication server
throw new AuthenticationServiceException("I/O error", ex);
}
catch (SMBException ex)
{
// Check the returned status code to determine why the logon failed and throw an appropriate exception
if ( ex.getErrorClass() == SMBStatus.NTErr)
{
AuthenticationException authEx = null;
switch( ex.getErrorCode())
{
case SMBStatus.NTLogonFailure:
authEx = new BadCredentialsException("Logon failure");
break;
case SMBStatus.NTAccountDisabled:
authEx = new DisabledException("Account disabled");
break;
default:
authEx = new BadCredentialsException("Logon failure");
break;
}
throw authEx;
}
else
throw new BadCredentialsException("Logon failure");
}
finally
{
// Make sure the authentication session is closed
if ( authSess != null)
{
try
{
// Remove the session from the active list
m_passthruSessions.remove(ntlmToken);
// Close the session to the authentication server
authSess.CloseSession();
}
catch (Exception ex)
{
}
}
}
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ntlm;
import org.alfresco.filesys.util.HexDump;
/**
* Contains the NTLM challenge bytes.
*
* @author GKSpencer
*/
public class NTLMChallenge
{
// Challenge bytes
private byte[] m_challenge;
/**
* Class constructor
*
* @param chbyts byte[]
*/
protected NTLMChallenge(byte[] chbyts)
{
m_challenge = chbyts;
}
/**
* Return the challenge bytes
*
* @return byte[]
*/
public final byte[] getBytes()
{
return m_challenge;
}
/**
* Check for object equality
*
* @param obj Object
* @return boolean
*/
public boolean equals(Object obj)
{
if ( obj instanceof NTLMChallenge)
{
NTLMChallenge ntlmCh = (NTLMChallenge) obj;
// Check if both challenges are null
if ( getBytes() == null && ntlmCh.getBytes() == null)
return true;
// Check if both challenges are the same length
if ( getBytes() != null && ntlmCh.getBytes() != null &&
getBytes().length == ntlmCh.getBytes().length)
{
// Check if challenages are the same value
byte[] ntlmBytes = ntlmCh.getBytes();
for ( int i = 0; i < m_challenge.length; i++)
if ( m_challenge[i] != ntlmBytes[i])
return false;
}
else
return false;
}
// Not the same type
return false;
}
/**
* Return the challenge as a string
*
* @return String
*/
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("[");
str.append(HexDump.hexString(getBytes(), " "));
str.append("]");
return str.toString();
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ntlm;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.providers.*;
/**
* <p>Used to provide authentication with a remote Windows server when the username and password are
* provided locally.
*
* @author GKSpencer
*/
public class NTLMLocalToken extends UsernamePasswordAuthenticationToken
{
private static final long serialVersionUID = -7946514578455279387L;
/**
* Class constructor
*/
protected NTLMLocalToken()
{
super(null, null);
}
/**
* Class constructor
*
* @param username String
* @param plainPwd String
*/
public NTLMLocalToken(String username, String plainPwd) {
super(username.toLowerCase(), plainPwd);
}
/**
* Check if the user logged on as a guest
*
* @return boolean
*/
public final boolean isGuestLogon()
{
return hasAuthority(NTLMAuthenticationProvider.NTLMAuthorityGuest);
}
/**
* Check if the user is an administrator
*
* @return boolean
*/
public final boolean isAdministrator()
{
return hasAuthority(NTLMAuthenticationProvider.NTLMAuthorityAdministrator);
}
/**
* Search for the specified authority
*
* @param authority String
* @return boolean
*/
public final boolean hasAuthority(String authority)
{
boolean found = false;
GrantedAuthority[] authorities = getAuthorities();
if ( authorities != null && authorities.length > 0)
{
// Search for the specified authority
int i = 0;
while ( found == false && i < authorities.length)
{
if ( authorities[i++].getAuthority().equals(authority))
found = true;
}
}
// Return the status
return found;
}
}

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ntlm;
/**
* <p>Used to provide passthru authentication to a remote Windows server using multiple stages that
* allows authentication details to be passed between a client and the remote authenticating server without
* the password being known by the authentication provider.
*
* @author GKSpencer
*/
public class NTLMPassthruToken extends NTLMLocalToken
{
private static final long serialVersionUID = -4635444888514735368L;
// Challenge for this session
private NTLMChallenge m_challenge;
// User name, hashed password and algorithm type
private String m_username;
private byte[] m_hashedPassword;
private int m_hashType;
// Time that the authentication session will expire
private long m_authExpiresAt;
/**
* Class constructor
*/
public NTLMPassthruToken()
{
// We do not know the username yet, and will not know the password
super("", "");
}
/**
* Return the challenge
*
* @return NTLMChallenge
*/
public final NTLMChallenge getChallenge()
{
return m_challenge;
}
/**
* Return the user account
*
* @return Object
*/
public final Object getPrincipal()
{
return m_username;
}
/**
* Return the hashed password
*
* @return byte[]
*/
public final byte[] getHashedPassword()
{
return m_hashedPassword;
}
/**
* Return the hashed password type
*
* @return int
*/
public final int getPasswordType()
{
return m_hashType;
}
/**
* Return the authentication expiry time, this will be zero if the authentication session has not yet
* been opened to the server
*
* @return long
*/
public final long getAuthenticationExpireTime()
{
return m_authExpiresAt;
}
/**
* Set the hashed password and type
*
* @param hashedPassword byte[]
* @param hashType int
*/
public final void setUserAndPassword(String username, byte[] hashedPassword, int hashType)
{
m_username = username.toLowerCase();
m_hashedPassword = hashedPassword;
m_hashType = hashType;
}
/**
* Set the challenge for this token
*
* @param challenge NTLMChallenge
*/
protected final void setChallenge(NTLMChallenge challenge)
{
m_challenge = challenge;
}
/**
* Set the authentication expire time, this indicates that an authentication session is associated with this
* token and the session will be closed if the authentication is not completed by this time.
*
* @param startTime long
*/
protected final void setAuthenticationExpireTime(long expireTime)
{
m_authExpiresAt = expireTime;
}
/**
* Check for object equality
*
* @param obj Object
* @return boolean
*/
public boolean equals(Object obj)
{
// Only match on the same object
return this == obj;
}
}

View File

@@ -0,0 +1,344 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authentication.ntlm;
import java.util.Date;
import net.sf.acegisecurity.UserDetails;
import net.sf.acegisecurity.providers.dao.UsernameNotFoundException;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.service.cmr.repository.NodeService;
import org.springframework.dao.DataAccessException;
/**
* Null Mutable Authentication Dao Class
*
* <p>Mutable authentication implementation that does nothing.
*
* @author GKSpencer
*/
public class NullMutableAuthenticationDao implements MutableAuthenticationDao
{
/**
* Method kept just for backward compatibility with older configurations that
* might have been passing in a value.
*
* @param nodeService ignored
*/
public void setNodeService(NodeService nodeService)
{
// do nothing
}
/**
* Create a user with the given userName and password
*
* @param userName
* @param rawPassword
* @throws AuthenticationException
*/
public void createUser(String userName, char[] rawPassword) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Update a user's password.
*
* @param userName
* @param rawPassword
* @throws AuthenticationException
*/
public void updateUser(String userName, char[] rawPassword) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Delete a user.
*
* @param userName
* @throws AuthenticationException
*/
public void deleteUser(String userName) throws AuthenticationException
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Check is a user exists.
*
* @param userName
* @return
*/
public boolean userExists(String userName)
{
return true;
}
/**
* Enable/disable a user.
*
* @param userName
* @param enabled
*/
public void setEnabled(String userName, boolean enabled)
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Getter for user enabled
*
* @param userName
* @return
*/
public boolean getEnabled(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return true;
}
/**
* Set if the account should expire
*
* @param userName
* @param expires
*/
public void setAccountExpires(String userName, boolean expires)
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Does the account expire?
*
* @param userName
* @return
*/
public boolean getAccountExpires(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Has the account expired?
*
* @param userName
* @return
*/
public boolean getAccountHasExpired(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Set if the password expires.
*
* @param userName
* @param expires
*/
public void setCredentialsExpire(String userName, boolean expires)
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Do the credentials for the user expire?
*
* @param userName
* @return
*/
public boolean getCredentialsExpire(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Have the credentials for the user expired?
*
* @param userName
* @return
*/
public boolean getCredentialsHaveExpired(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Set if the account is locked.
*
* @param userName
* @param locked
*/
public void setLocked(String userName, boolean locked)
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Is the account locked?
*
* @param userName
* @return
*/
public boolean getAccountlocked(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Set the date on which the account expires
*
* @param userName
* @param exipryDate
*/
public void setAccountExpiryDate(String userName, Date exipryDate)
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Get the date when this account expires.
*
* @param userName
* @return
*/
public Date getAccountExpiryDate(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return null;
}
/**
* Set the date when credentials expire.
*
* @param userName
* @param exipryDate
*/
public void setCredentialsExpiryDate(String userName, Date exipryDate)
{
throw new AlfrescoRuntimeException("Not implemented");
// Nothing to do
}
/**
* Get the date when the credentials/password expire.
*
* @param userName
* @return
*/
public Date getCredentialsExpiryDate(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return null;
}
/**
* Get the MD4 password hash
*
* @param userName
* @return
*/
public String getMD4HashedPassword(String userName)
{
throw new AlfrescoRuntimeException("Not implemented");
// return null;
}
/**
* Are user names case sensitive?
*
* @return
*/
public boolean getUserNamesAreCaseSensitive()
{
throw new AlfrescoRuntimeException("Not implemented");
// return false;
}
/**
* Return the user details for the specified user
*
* @param user String
* @return UserDetails
* @exception UsernameNotFoundException
* @exception DataAccessException
*/
public UserDetails loadUserByUsername(String arg0) throws UsernameNotFoundException, DataAccessException
{
throw new AlfrescoRuntimeException("Not implemented");
// return null;
}
/**
* Return salt for user
*
* @param user UserDetails
* @return Object
*/
public Object getSalt(UserDetails user)
{
throw new AlfrescoRuntimeException("Not implemented");
// return null;
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
import java.util.Set;
import org.alfresco.service.cmr.security.AuthorityType;
public interface AuthorityDAO
{
/**
* Add an authority to another.
*
* @param parentName
* @param childName
*/
void addAuthority(String parentName, String childName);
/**
* Create an authority.
*
* @param parentName
* @param name
*/
void createAuthority(String parentName, String name);
/**
* Delete an authority.
*
* @param name
*/
void deleteAuthority(String name);
/**
* Get all root authorities.
*
* @param type
* @return
*/
Set<String> getAllRootAuthorities(AuthorityType type);
/**
* Get contained authorities.
*
* @param type
* @param name
* @param immediate
* @return
*/
Set<String> getContainedAuthorities(AuthorityType type, String name, boolean immediate);
/**
* Remove an authority.
*
* @param parentName
* @param childName
*/
void removeAuthority(String parentName, String childName);
/**
* Get the authorities that contain the one given.
*
* @param type
* @param name
* @param immediate
* @return
*/
Set<String> getContainingAuthorities(AuthorityType type, String name, boolean immediate);
/**
* Get all authorities by type
*
* @param type
* @return
*/
Set<String> getAllAuthorities(AuthorityType type);
}

View File

@@ -0,0 +1,488 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.search.impl.lucene.QueryParser;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.ResultSetRow;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ISO9075;
public class AuthorityDAOImpl implements AuthorityDAO
{
private static final StoreRef STOREREF_USERS = new StoreRef("user", "alfrescoUserStore");
private NodeService nodeService;
private NamespacePrefixResolver namespacePrefixResolver;
private QName qnameAssocSystem;
private QName qnameAssocAuthorities;
private SearchService searchService;
private DictionaryService dictionaryService;
private SimpleCache<String, ArrayList<NodeRef>> userToAuthorityCache;
public AuthorityDAOImpl()
{
super();
}
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
public void setNamespacePrefixResolver(NamespacePrefixResolver namespacePrefixResolver)
{
this.namespacePrefixResolver = namespacePrefixResolver;
qnameAssocSystem = QName.createQName("sys", "system", namespacePrefixResolver);
qnameAssocAuthorities = QName.createQName("sys", "authorities", namespacePrefixResolver);
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setUserToAuthorityCache(SimpleCache<String, ArrayList<NodeRef>> userToAuthorityCache)
{
this.userToAuthorityCache = userToAuthorityCache;
}
public void addAuthority(String parentName, String childName)
{
NodeRef parentRef = getAuthorityOrNull(parentName);
if (parentRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + parentName);
}
if (AuthorityType.getAuthorityType(childName).equals(AuthorityType.USER))
{
Collection<String> memberCollection = DefaultTypeConverter.INSTANCE.getCollection(String.class, nodeService
.getProperty(parentRef, ContentModel.PROP_MEMBERS));
HashSet<String> members = new HashSet<String>();
members.addAll(memberCollection);
members.add(childName);
nodeService.setProperty(parentRef, ContentModel.PROP_MEMBERS, members);
userToAuthorityCache.remove(childName);
}
else
{
NodeRef childRef = getAuthorityOrNull(childName);
if (childRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + childName);
}
nodeService.addChild(
parentRef,
childRef,
ContentModel.ASSOC_MEMBER,
QName.createQName("usr", childName, namespacePrefixResolver));
}
}
public void createAuthority(String parentName, String name)
{
HashMap<QName, Serializable> props = new HashMap<QName, Serializable>();
props.put(ContentModel.PROP_AUTHORITY_NAME, name);
if (parentName != null)
{
NodeRef parentRef = getAuthorityOrNull(parentName);
if (parentRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + parentName);
}
nodeService.createNode(
parentRef,
ContentModel.ASSOC_MEMBER,
QName.createQName("usr", name, namespacePrefixResolver),
ContentModel.TYPE_AUTHORITY_CONTAINER,
props);
}
else
{
NodeRef authorityContainerRef = getAuthorityContainer();
nodeService.createNode(
authorityContainerRef,
ContentModel.ASSOC_MEMBER,
QName.createQName("usr", name, namespacePrefixResolver),
ContentModel.TYPE_AUTHORITY_CONTAINER,
props);
}
}
public void deleteAuthority(String name)
{
NodeRef nodeRef = getAuthorityOrNull(name);
if (nodeRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + name);
}
nodeService.deleteNode(nodeRef);
}
public Set<String> getAllRootAuthorities(AuthorityType type)
{
HashSet<String> authorities = new HashSet<String>();
NodeRef container = getAuthorityContainer();
if (container != null)
{
findAuthorities(type, container, authorities, false, false, false);
}
return authorities;
}
public Set<String> getAllAuthorities(AuthorityType type)
{
HashSet<String> authorities = new HashSet<String>();
NodeRef container = getAuthorityContainer();
if (container != null)
{
findAuthorities(type, container, authorities, false, true, false);
}
return authorities;
}
public Set<String> getContainedAuthorities(AuthorityType type, String name, boolean immediate)
{
if (AuthorityType.getAuthorityType(name).equals(AuthorityType.USER))
{
return Collections.<String> emptySet();
}
else
{
NodeRef nodeRef = getAuthorityOrNull(name);
if (nodeRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + name);
}
HashSet<String> authorities = new HashSet<String>();
findAuthorities(type, nodeRef, authorities, false, !immediate, false);
return authorities;
}
}
public void removeAuthority(String parentName, String childName)
{
NodeRef parentRef = getAuthorityOrNull(parentName);
if (parentRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + parentName);
}
if (AuthorityType.getAuthorityType(childName).equals(AuthorityType.USER))
{
Collection<String> memberCollection = DefaultTypeConverter.INSTANCE.getCollection(String.class, nodeService
.getProperty(parentRef, ContentModel.PROP_MEMBERS));
HashSet<String> members = new HashSet<String>();
members.addAll(memberCollection);
members.remove(childName);
nodeService.setProperty(parentRef, ContentModel.PROP_MEMBERS, members);
userToAuthorityCache.remove(childName);
}
else
{
NodeRef childRef = getAuthorityOrNull(childName);
if (childRef == null)
{
throw new UnknownAuthorityException("An authority was not found for " + childName);
}
nodeService.removeChild(parentRef, childRef);
}
}
public Set<String> getContainingAuthorities(AuthorityType type, String name, boolean immediate)
{
HashSet<String> authorities = new HashSet<String>();
findAuthorities(type, name, authorities, true, !immediate);
return authorities;
}
private void findAuthorities(AuthorityType type, String name, Set<String> authorities, boolean parents,
boolean recursive)
{
if (AuthorityType.getAuthorityType(name).equals(AuthorityType.GUEST))
{
// Nothing to do
}
else if (AuthorityType.getAuthorityType(name).equals(AuthorityType.USER))
{
for (NodeRef ref : getUserContainers(name))
{
findAuthorities(type, ref, authorities, parents, recursive, true);
}
}
else
{
NodeRef ref = getAuthorityOrNull(name);
if (ref == null)
{
throw new UnknownAuthorityException("An authority was not found for " + name);
}
findAuthorities(type, ref, authorities, parents, recursive, false);
}
}
private ArrayList<NodeRef> getUserContainers(String name)
{
ArrayList<NodeRef> containers = userToAuthorityCache.get(name);
if (containers == null)
{
containers = findUserContainers(name);
userToAuthorityCache.put(name, containers);
}
return containers;
}
private ArrayList<NodeRef> findUserContainers(String name)
{
SearchParameters sp = new SearchParameters();
sp.addStore(STOREREF_USERS);
sp.setLanguage("lucene");
sp.setQuery("+TYPE:\""
+ ContentModel.TYPE_AUTHORITY_CONTAINER
+ "\""
+ " +@"
+ QueryParser.escape("{"
+ ContentModel.PROP_MEMBERS.getNamespaceURI() + "}"
+ ISO9075.encode(ContentModel.PROP_MEMBERS.getLocalName())) + ":\"" + name + "\"");
ResultSet rs = null;
try
{
rs = searchService.query(sp);
ArrayList<NodeRef> answer = new ArrayList<NodeRef>(rs.length());
for (ResultSetRow row : rs)
{
answer.add(row.getNodeRef());
}
return answer;
}
finally
{
if (rs != null)
{
rs.close();
}
}
}
private void findAuthorities(AuthorityType type, NodeRef nodeRef, Set<String> authorities, boolean parents,
boolean recursive, boolean includeNode)
{
List<ChildAssociationRef> cars = parents ? nodeService.getParentAssocs(nodeRef) : nodeService
.getChildAssocs(nodeRef);
if (includeNode)
{
String authorityName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(nodeRef,
ContentModel.PROP_AUTHORITY_NAME));
if (type == null)
{
authorities.add(authorityName);
}
else
{
AuthorityType authorityType = AuthorityType.getAuthorityType(authorityName);
if (authorityType.equals(type))
{
authorities.add(authorityName);
}
}
}
// Loop over children
for (ChildAssociationRef car : cars)
{
NodeRef current = parents ? car.getParentRef() : car.getChildRef();
QName currentType = nodeService.getType(current);
if (dictionaryService.isSubClass(currentType, ContentModel.TYPE_AUTHORITY))
{
String authorityName = DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(
current, ContentModel.PROP_AUTHORITY_NAME));
if (type == null)
{
authorities.add(authorityName);
if (recursive)
{
findAuthorities(type, current, authorities, parents, recursive, false);
}
}
else
{
AuthorityType authorityType = AuthorityType.getAuthorityType(authorityName);
if (authorityType.equals(type))
{
authorities.add(authorityName);
}
if (recursive)
{
findAuthorities(type, current, authorities, parents, recursive, false);
}
}
}
}
// loop over properties
if (!parents)
{
Collection<String> members = DefaultTypeConverter.INSTANCE.getCollection(String.class, nodeService
.getProperty(nodeRef, ContentModel.PROP_MEMBERS));
if (members != null)
{
for (String user : members)
{
if (user != null)
{
if (type == null)
{
authorities.add(user);
}
else
{
AuthorityType authorityType = AuthorityType.getAuthorityType(user);
if (authorityType.equals(type))
{
authorities.add(user);
}
}
}
}
}
}
}
private NodeRef getAuthorityOrNull(String name)
{
SearchParameters sp = new SearchParameters();
sp.addStore(STOREREF_USERS);
sp.setLanguage("lucene");
sp.setQuery("+TYPE:\""
+ ContentModel.TYPE_AUTHORITY_CONTAINER
+ "\""
+ " +@"
+ QueryParser.escape("{"
+ ContentModel.PROP_AUTHORITY_NAME.getNamespaceURI() + "}"
+ ISO9075.encode(ContentModel.PROP_AUTHORITY_NAME.getLocalName())) + ":\"" + name + "\"");
ResultSet rs = null;
try
{
rs = searchService.query(sp);
if (rs.length() == 0)
{
return null;
}
else
{
for (ResultSetRow row : rs)
{
String test = DefaultTypeConverter.INSTANCE.convert(
String.class,
nodeService.getProperty(row.getNodeRef(), ContentModel.PROP_AUTHORITY_NAME));
if (test.equals(name))
{
return row.getNodeRef();
}
}
}
return null;
}
finally
{
if (rs != null)
{
rs.close();
}
}
}
/**
* @return Returns the authority container, <b>which must exist</b>
*/
private NodeRef getAuthorityContainer()
{
NodeRef rootNodeRef = nodeService.getRootNode(STOREREF_USERS);
List<ChildAssociationRef> results = nodeService.getChildAssocs(
rootNodeRef,
RegexQNamePattern.MATCH_ALL,
qnameAssocSystem);
NodeRef sysNodeRef = null;
if (results.size() == 0)
{
throw new AlfrescoRuntimeException("Required authority system path not found: " + qnameAssocSystem);
}
else
{
sysNodeRef = results.get(0).getChildRef();
}
results = nodeService.getChildAssocs(
sysNodeRef,
RegexQNamePattern.MATCH_ALL,
qnameAssocAuthorities);
NodeRef authNodeRef = null;
if (results.size() == 0)
{
throw new AlfrescoRuntimeException("Required authority path not found: " + qnameAssocAuthorities);
}
else
{
authNodeRef = results.get(0).getChildRef();
}
return authNodeRef;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
import org.alfresco.error.AlfrescoRuntimeException;
public class AuthorityException extends AlfrescoRuntimeException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = -5367993045129604445L;
public AuthorityException(String msgId)
{
super(msgId);
}
public AuthorityException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public AuthorityException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public AuthorityException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}

View File

@@ -0,0 +1,251 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.permissions.PermissionServiceSPI;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
/**
* The default implementation of the authority service.
*
* @author Andy Hind
*/
public class AuthorityServiceImpl implements AuthorityService
{
private PersonService personService;
private NodeService nodeService;
private AuthorityDAO authorityDAO;
private PermissionServiceSPI permissionServiceSPI;
private Set<String> adminSet = Collections.singleton(PermissionService.ADMINISTRATOR_AUTHORITY);
private Set<String> guestSet = Collections.singleton(PermissionService.GUEST_AUTHORITY);
private Set<String> allSet = Collections.singleton(PermissionService.ALL_AUTHORITIES);
private Set<String> adminUsers;
private AuthenticationComponent authenticationComponent;
public AuthorityServiceImpl()
{
super();
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setPersonService(PersonService personService)
{
this.personService = personService;
}
public void setAuthorityDAO(AuthorityDAO authorityDAO)
{
this.authorityDAO = authorityDAO;
}
public void setPermissionServiceSPI(PermissionServiceSPI permissionServiceSPI)
{
this.permissionServiceSPI = permissionServiceSPI;
}
/**
* Currently the admin authority is granted only to the ALFRESCO_ADMIN_USER
* user.
*/
public boolean hasAdminAuthority()
{
String currentUserName = authenticationComponent.getCurrentUserName();
return ((currentUserName != null) && adminUsers.contains(currentUserName));
}
// IOC
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
{
this.authenticationComponent = authenticationComponent;
}
public void setAdminUsers(Set<String> adminUsers)
{
this.adminUsers = adminUsers;
}
public Set<String> getAuthorities()
{
Set<String> authorities = new HashSet<String>();
String currentUserName = authenticationComponent.getCurrentUserName();
if (adminUsers.contains(currentUserName))
{
authorities.addAll(adminSet);
}
if(AuthorityType.getAuthorityType(currentUserName) != AuthorityType.GUEST)
{
authorities.addAll(allSet);
}
authorities.addAll(getContainingAuthorities(null, currentUserName, false));
return authorities;
}
public Set<String> getAllAuthorities(AuthorityType type)
{
Set<String> authorities = new HashSet<String>();
switch (type)
{
case ADMIN:
authorities.addAll(adminSet);
break;
case EVERYONE:
authorities.addAll(allSet);
break;
case GUEST:
authorities.addAll(guestSet);
break;
case GROUP:
authorities.addAll(authorityDAO.getAllAuthorities(type));
break;
case OWNER:
break;
case ROLE:
authorities.addAll(authorityDAO.getAllAuthorities(type));
break;
case USER:
for (NodeRef personRef : personService.getAllPeople())
{
authorities.add(DefaultTypeConverter.INSTANCE.convert(String.class, nodeService.getProperty(personRef,
ContentModel.PROP_USERNAME)));
}
break;
default:
break;
}
return authorities;
}
public void addAuthority(String parentName, String childName)
{
authorityDAO.addAuthority(parentName, childName);
}
private void checkTypeIsMutable(AuthorityType type)
{
if((type == AuthorityType.GROUP) || (type == AuthorityType.ROLE))
{
return;
}
else
{
throw new AuthorityException("Trying to modify a fixed authority");
}
}
public String createAuthority(AuthorityType type, String parentName, String shortName)
{
checkTypeIsMutable(type);
String name = getName(type, shortName);
authorityDAO.createAuthority(parentName, name);
return name;
}
public void deleteAuthority(String name)
{
AuthorityType type = AuthorityType.getAuthorityType(name);
checkTypeIsMutable(type);
authorityDAO.deleteAuthority(name);
permissionServiceSPI.deletePermissions(name);
}
public Set<String> getAllRootAuthorities(AuthorityType type)
{
return authorityDAO.getAllRootAuthorities(type);
}
public Set<String> getContainedAuthorities(AuthorityType type, String name, boolean immediate)
{
return authorityDAO.getContainedAuthorities(type, name, immediate);
}
public Set<String> getContainingAuthorities(AuthorityType type, String name, boolean immediate)
{
return authorityDAO.getContainingAuthorities(type, name, immediate);
}
public String getName(AuthorityType type, String shortName)
{
if (type.isFixedString())
{
return type.getFixedString();
}
else if (type.isPrefixed())
{
return type.getPrefixString() + shortName;
}
else
{
return shortName;
}
}
public String getShortName(String name)
{
AuthorityType type = AuthorityType.getAuthorityType(name);
if (type.isFixedString())
{
return "";
}
else if (type.isPrefixed())
{
return name.substring(type.getPrefixString().length());
}
else
{
return name;
}
}
public void removeAuthority(String parentName, String childName)
{
authorityDAO.removeAuthority(parentName, childName);
}
}

View File

@@ -0,0 +1,517 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
import javax.transaction.UserTransaction;
import junit.framework.TestCase;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.MutableAuthenticationDao;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.ApplicationContextHelper;
import org.springframework.context.ApplicationContext;
public class AuthorityServiceTest extends TestCase
{
private static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
private AuthenticationComponent authenticationComponent;
private AuthenticationComponent authenticationComponentImpl;
private AuthenticationService authenticationService;
private MutableAuthenticationDao authenticationDAO;
private AuthorityService authorityService;
private AuthorityService pubAuthorityService;
private PersonService personService;
private UserTransaction tx;
public AuthorityServiceTest()
{
super();
}
public void setUp() throws Exception
{
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
authenticationComponentImpl = (AuthenticationComponent) ctx.getBean("authenticationComponentImpl");
authenticationService = (AuthenticationService) ctx.getBean("authenticationService");
authorityService = (AuthorityService) ctx.getBean("authorityService");
pubAuthorityService = (AuthorityService) ctx.getBean("AuthorityService");
personService = (PersonService) ctx.getBean("personService");
authenticationDAO = (MutableAuthenticationDao) ctx.getBean("authenticationDao");
authenticationComponentImpl.setSystemUserAsCurrentUser();
TransactionService transactionService = (TransactionService) ctx.getBean(ServiceRegistry.TRANSACTION_SERVICE
.getLocalName());
tx = transactionService.getUserTransaction();
tx.begin();
if (!authenticationDAO.userExists("andy"))
{
authenticationService.createAuthentication("andy", "andy".toCharArray());
}
if (!authenticationDAO.userExists("admin"))
{
authenticationService.createAuthentication("admin", "admin".toCharArray());
}
if (!authenticationDAO.userExists("administrator"))
{
authenticationService.createAuthentication("administrator", "administrator".toCharArray());
}
}
@Override
protected void tearDown() throws Exception
{
authenticationComponentImpl.clearCurrentSecurityContext();
tx.rollback();
super.tearDown();
}
public void testNonAdminUser()
{
authenticationComponent.setCurrentUser("andy");
assertFalse(authorityService.hasAdminAuthority());
assertFalse(pubAuthorityService.hasAdminAuthority());
assertEquals(1, authorityService.getAuthorities().size());
}
public void testAdminUser()
{
authenticationComponent.setCurrentUser("admin");
assertTrue(authorityService.hasAdminAuthority());
assertTrue(pubAuthorityService.hasAdminAuthority());
assertEquals(2, authorityService.getAuthorities().size());
authenticationComponent.setCurrentUser("administrator");
assertTrue(authorityService.hasAdminAuthority());
assertTrue(pubAuthorityService.hasAdminAuthority());
assertEquals(2, authorityService.getAuthorities().size());
}
public void testAuthorities()
{
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.ADMIN).size());
assertTrue(pubAuthorityService.getAllAuthorities(AuthorityType.ADMIN).contains(
PermissionService.ADMINISTRATOR_AUTHORITY));
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.EVERYONE).size());
assertTrue(pubAuthorityService.getAllAuthorities(AuthorityType.EVERYONE).contains(
PermissionService.ALL_AUTHORITIES));
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertFalse(pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).contains(
PermissionService.ALL_AUTHORITIES));
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GUEST).size());
assertTrue(pubAuthorityService.getAllAuthorities(AuthorityType.GUEST).contains(PermissionService.GUEST_AUTHORITY));
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.OWNER).size());
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(personService.getAllPeople().size(), pubAuthorityService.getAllAuthorities(AuthorityType.USER)
.size());
}
public void testCreateAdminAuth()
{
try
{
pubAuthorityService.createAuthority(AuthorityType.ADMIN, null, "woof");
fail("Should not be able to create an admin authority");
}
catch (AuthorityException ae)
{
}
}
public void testCreateEveryoneAuth()
{
try
{
pubAuthorityService.createAuthority(AuthorityType.EVERYONE, null, "woof");
fail("Should not be able to create an everyone authority");
}
catch (AuthorityException ae)
{
}
}
public void testCreateGuestAuth()
{
try
{
pubAuthorityService.createAuthority(AuthorityType.GUEST, null, "woof");
fail("Should not be able to create an guest authority");
}
catch (AuthorityException ae)
{
}
}
public void testCreateOwnerAuth()
{
try
{
pubAuthorityService.createAuthority(AuthorityType.OWNER, null, "woof");
fail("Should not be able to create an owner authority");
}
catch (AuthorityException ae)
{
}
}
public void testCreateUserAuth()
{
try
{
pubAuthorityService.createAuthority(AuthorityType.USER, null, "woof");
fail("Should not be able to create an user authority");
}
catch (AuthorityException ae)
{
}
}
public void testCreateRootAuth()
{
String auth;
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "woof");
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
pubAuthorityService.deleteAuthority(auth);
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
auth = pubAuthorityService.createAuthority(AuthorityType.ROLE, null, "woof");
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
pubAuthorityService.deleteAuthority(auth);
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
}
public void testCreateAuth()
{
String auth1;
String auth2;
String auth3;
String auth4;
String auth5;
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth1 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "one");
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth2 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "two");
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth3 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "three");
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth4 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "four");
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth5 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth2, "five");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
pubAuthorityService.deleteAuthority(auth5);
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
pubAuthorityService.deleteAuthority(auth4);
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
pubAuthorityService.deleteAuthority(auth3);
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
pubAuthorityService.deleteAuthority(auth2);
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
pubAuthorityService.deleteAuthority(auth1);
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
auth1 = pubAuthorityService.createAuthority(AuthorityType.ROLE, null, "one");
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
auth2 = pubAuthorityService.createAuthority(AuthorityType.ROLE, null, "two");
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
auth3 = pubAuthorityService.createAuthority(AuthorityType.ROLE, auth1, "three");
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
auth4 = pubAuthorityService.createAuthority(AuthorityType.ROLE, auth1, "four");
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
auth5 = pubAuthorityService.createAuthority(AuthorityType.ROLE, auth2, "five");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
pubAuthorityService.deleteAuthority(auth5);
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
pubAuthorityService.deleteAuthority(auth4);
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
pubAuthorityService.deleteAuthority(auth3);
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
pubAuthorityService.deleteAuthority(auth2);
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
pubAuthorityService.deleteAuthority(auth1);
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.ROLE).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.ROLE).size());
}
public void testCreateAuthTree()
{
String auth1;
String auth2;
String auth3;
String auth4;
String auth5;
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth1 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "one");
assertEquals("GROUP_one", auth1);
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth2 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "two");
assertEquals("GROUP_two", auth2);
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth3 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "three");
assertEquals("GROUP_three", auth3);
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth4 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "four");
assertEquals("GROUP_four", auth4);
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth5 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth2, "five");
assertEquals("GROUP_five", auth5);
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
pubAuthorityService.addAuthority(auth5, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(2, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
assertEquals(1, pubAuthorityService.getContainingAuthorities(null, auth5, false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, auth5, false).contains(auth2));
assertEquals(2, pubAuthorityService.getContainedAuthorities(null, auth2, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains(auth5));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains("andy"));
assertEquals(1, pubAuthorityService.getContainedAuthorities(null, auth5, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth5, false).contains("andy"));
pubAuthorityService.removeAuthority(auth5, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(0, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertEquals(1, pubAuthorityService.getContainingAuthorities(null, auth5, false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, auth5, false).contains(auth2));
assertEquals(1, pubAuthorityService.getContainedAuthorities(null, auth2, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains(auth5));
assertEquals(0, pubAuthorityService.getContainedAuthorities(null, auth5, false).size());
}
public void testCreateAuthNet()
{
String auth1;
String auth2;
String auth3;
String auth4;
String auth5;
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth1 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "one");
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth2 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "two");
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth3 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "three");
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth4 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "four");
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth5 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth2, "five");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
pubAuthorityService.addAuthority(auth5, "andy");
pubAuthorityService.addAuthority(auth1, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth1));
assertEquals(2, pubAuthorityService.getContainedAuthorities(null, auth2, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains(auth5));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains("andy"));
assertEquals(3, pubAuthorityService.getContainedAuthorities(null, auth1, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth3));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth4));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains("andy"));
pubAuthorityService.removeAuthority(auth1, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(2, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
assertEquals(2, pubAuthorityService.getContainedAuthorities(null, auth2, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains(auth5));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains("andy"));
assertEquals(2, pubAuthorityService.getContainedAuthorities(null, auth1, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth3));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth4));
}
public void testCreateAuthNet2()
{
String auth1;
String auth2;
String auth3;
String auth4;
String auth5;
assertEquals(0, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(0, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth1 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "one");
assertEquals(1, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(1, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth2 = pubAuthorityService.createAuthority(AuthorityType.GROUP, null, "two");
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth3 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "three");
assertEquals(3, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth4 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth1, "four");
assertEquals(4, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
auth5 = pubAuthorityService.createAuthority(AuthorityType.GROUP, auth2, "five");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
pubAuthorityService.addAuthority(auth5, "andy");
pubAuthorityService.addAuthority(auth1, "andy");
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(3, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth1));
assertEquals(2, pubAuthorityService.getContainedAuthorities(null, auth2, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains(auth5));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains("andy"));
assertEquals(3, pubAuthorityService.getContainedAuthorities(null, auth1, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth3));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth4));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains("andy"));
pubAuthorityService.addAuthority(auth3, auth2);
assertEquals(5, pubAuthorityService.getAllAuthorities(AuthorityType.GROUP).size());
assertEquals(2, pubAuthorityService.getAllRootAuthorities(AuthorityType.GROUP).size());
// The next call looks for people not users :-)
assertEquals(2, pubAuthorityService.getAllAuthorities(AuthorityType.USER).size());
assertEquals(4, pubAuthorityService.getContainingAuthorities(null, "andy", false).size());
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth5));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth2));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth1));
assertTrue(pubAuthorityService.getContainingAuthorities(null, "andy", false).contains(auth3));
assertEquals(2, pubAuthorityService.getContainedAuthorities(null, auth2, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains(auth5));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth2, false).contains("andy"));
assertEquals(5, pubAuthorityService.getContainedAuthorities(null, auth1, false).size());
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth3));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth4));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth2));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains(auth5));
assertTrue(pubAuthorityService.getContainedAuthorities(null, auth1, false).contains("andy"));
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
import org.alfresco.repo.security.permissions.impl.AbstractPermissionTest;
import org.alfresco.repo.security.permissions.impl.SimplePermissionEntry;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.cmr.security.PermissionService;
public class ExtendedPermissionServiceTest extends AbstractPermissionTest
{
public void testGroupPermission()
{
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ),
"GROUP_test", AccessStatus.ALLOWED));
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
authorityService.createAuthority(AuthorityType.GROUP, null, "test");
authorityService.addAuthority("GROUP_test", "andy");
assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
authorityService.removeAuthority("GROUP_test", "andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
permissionService.clearPermission(rootNodeRef, "andy");
}
public void testDeletePermissionByRecipient()
{
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ),
"GROUP_test", AccessStatus.ALLOWED));
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
authorityService.createAuthority(AuthorityType.GROUP, null, "test");
authorityService.addAuthority("GROUP_test", "andy");
assertTrue(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
permissionService.deletePermissions("GROUP_test");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Alfresco Network License. You may obtain a
* copy of the License at
*
* http://www.alfrescosoftware.com/legal/
*
* Please view the license relevant to your network subscription.
*
* BY CLICKING THE "I UNDERSTAND AND ACCEPT" BOX, OR INSTALLING,
* READING OR USING ALFRESCO'S Network SOFTWARE (THE "SOFTWARE"),
* YOU ARE AGREEING ON BEHALF OF THE ENTITY LICENSING THE SOFTWARE
* ("COMPANY") THAT COMPANY WILL BE BOUND BY AND IS BECOMING A PARTY TO
* THIS ALFRESCO NETWORK AGREEMENT ("AGREEMENT") AND THAT YOU HAVE THE
* AUTHORITY TO BIND COMPANY. IF COMPANY DOES NOT AGREE TO ALL OF THE
* TERMS OF THIS AGREEMENT, DO NOT SELECT THE "I UNDERSTAND AND AGREE"
* BOX AND DO NOT INSTALL THE SOFTWARE OR VIEW THE SOURCE CODE. COMPANY
* HAS NOT BECOME A LICENSEE OF, AND IS NOT AUTHORIZED TO USE THE
* SOFTWARE UNLESS AND UNTIL IT HAS AGREED TO BE BOUND BY THESE LICENSE
* TERMS. THE "EFFECTIVE DATE" FOR THIS AGREEMENT SHALL BE THE DAY YOU
* CHECK THE "I UNDERSTAND AND ACCEPT" BOX.
*/
package org.alfresco.repo.security.authority;
public class UnknownAuthorityException extends AuthorityException
{
/**
* Comment for <code>serialVersionUID</code>
*/
private static final long serialVersionUID = 4639634037108317201L;
public UnknownAuthorityException(String msgId)
{
super(msgId);
}
public UnknownAuthorityException(String msgId, Object[] msgParams)
{
super(msgId, msgParams);
}
public UnknownAuthorityException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public UnknownAuthorityException(String msgId, Object[] msgParams, Throwable cause)
{
super(msgId, msgParams, cause);
}
}