Added: james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultJamesUser.java URL: http://svn.apache.org/viewvc/james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultJamesUser.java?rev=599566&view=auto ============================================================================== --- james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultJamesUser.java (added) +++ james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultJamesUser.java Thu Nov 29 12:08:58 2007 @@ -0,0 +1,141 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + + + +package org.apache.james.userrepository; + +import org.apache.james.services.JamesUser; +import org.apache.mailet.MailAddress; + +/** + * Implementation of User Interface. + * + * + * @version $Revision: 521427 $ + */ + +public class DefaultJamesUser + extends DefaultUser + implements JamesUser { + + private static final long serialVersionUID = 6323959976390389529L; + + /** + * Whether forwarding is enabled for this user. + */ + private boolean forwarding; + + /** + * The mail address to which this user's email is forwarded. + */ + private MailAddress forwardingDestination; + + /** + * Is this user an alias for another username on the system. + */ + private boolean aliasing; + + + /** + * The user name that this user name is aliasing. + */ + private String alias; + + public DefaultJamesUser(String name, String alg) { + super(name, alg); + initialize(); + } + + public DefaultJamesUser(String name, String passwordHash, String hashAlg) { + super(name, passwordHash, hashAlg); + initialize(); + } + + + /** + * Initializes default values for local fields. + */ + public void initialize() { + forwarding = false; + forwardingDestination = null; + aliasing = false; + alias = ""; + } + + /** + * @see org.apache.james.services.JamesUser#setForwarding(boolean) + */ + public void setForwarding(boolean forward) { + forwarding = forward; + } + + /** + * @see org.apache.james.services.JamesUser#getForwarding() + */ + public boolean getForwarding() { + return forwarding; + } + + /** + * @see org.apache.james.services.JamesUser#setForwardingDestination(org.apache.mailet.MailAddress) + */ + public boolean setForwardingDestination(MailAddress address) { + /* TODO: Some verification would be good */ + forwardingDestination = address; + return true; + } + + /** + * @see org.apache.james.services.JamesUser#getForwardingDestination() + */ + public MailAddress getForwardingDestination() { + return forwardingDestination; + } + + /** + * @see org.apache.james.services.JamesUser#setAliasing(boolean) + */ + public void setAliasing(boolean alias) { + aliasing = alias; + } + + /** + * @see org.apache.james.services.JamesUser#getAliasing() + */ + public boolean getAliasing() { + return aliasing; + } + + /** + * @see org.apache.james.services.JamesUser#setAlias(java.lang.String) + */ + public boolean setAlias(String address) { + /* TODO: Some verification would be good */ + alias = address; + return true; + } + + /** + * @see org.apache.james.services.JamesUser#getAlias() + */ + public String getAlias() { + return alias; + } +}
Added: james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultUser.java URL: http://svn.apache.org/viewvc/james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultUser.java?rev=599566&view=auto ============================================================================== --- james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultUser.java (added) +++ james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/DefaultUser.java Thu Nov 29 12:08:58 2007 @@ -0,0 +1,120 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + + + +package org.apache.james.userrepository; + +import org.apache.james.security.DigestUtil; +import org.apache.james.services.User; + +import java.io.Serializable; +import java.security.NoSuchAlgorithmException; + +/** + * Implementation of User Interface. Instances of this class do not allow + * the the user name to be reset. + * + * + * @version CVS $Revision: 521427 $ + */ + +public class DefaultUser implements User, Serializable { + + private static final long serialVersionUID = 5178048915868531270L; + + private String userName; + private String hashedPassword; + private String algorithm ; + + /** + * Standard constructor. + * + * @param name the String name of this user + * @param hashAlg the algorithm used to generate the hash of the password + */ + public DefaultUser(String name, String hashAlg) { + userName = name; + algorithm = hashAlg; + } + + /** + * Constructor for repositories that are construcing user objects from + * separate fields, e.g. databases. + * + * @param name the String name of this user + * @param passwordHash the String hash of this users current password + * @param hashAlg the String algorithm used to generate the hash of the + * password + */ + public DefaultUser(String name, String passwordHash, String hashAlg) { + userName = name; + hashedPassword = passwordHash; + algorithm = hashAlg; + } + + /** + * @see org.apache.james.services.User#getUserName() + */ + public String getUserName() { + return userName; + } + + /** + * @see org.apache.james.services.User#verifyPassword(java.lang.String) + */ + public boolean verifyPassword(String pass) { + try { + String hashGuess = DigestUtil.digestString(pass, algorithm); + return hashedPassword.equals(hashGuess); + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException("Security error: " + nsae); + } + } + + /** + * @see org.apache.james.services.User#setPassword(java.lang.String) + */ + public boolean setPassword(String newPass) { + try { + hashedPassword = DigestUtil.digestString(newPass, algorithm); + return true; + } catch (NoSuchAlgorithmException nsae) { + throw new RuntimeException("Security error: " + nsae); + } + } + + /** + * Method to access hash of password + * + * @return the String of the hashed Password + */ + protected String getHashedPassword() { + return hashedPassword; + } + + /** + * Method to access the hashing algorithm of the password. + * + * @return the name of the hashing algorithm used for this user's password + */ + protected String getHashAlgorithm() { + return algorithm; + } +} Added: james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersFileRepository.java URL: http://svn.apache.org/viewvc/james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersFileRepository.java?rev=599566&view=auto ============================================================================== --- james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersFileRepository.java (added) +++ james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersFileRepository.java Thu Nov 29 12:08:58 2007 @@ -0,0 +1,295 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + + + +package org.apache.james.userrepository; + +import org.apache.avalon.cornerstone.services.store.ObjectRepository; +import org.apache.avalon.cornerstone.services.store.Store; +import org.apache.avalon.framework.activity.Initializable; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.avalon.framework.configuration.DefaultConfiguration; +import org.apache.avalon.framework.service.ServiceException; +import org.apache.avalon.framework.service.ServiceManager; +import org.apache.avalon.framework.service.Serviceable; +import org.apache.james.services.User; +import org.apache.james.userrepository.AbstractUsersRepository; +import org.apache.james.userrepository.DefaultJamesUser; + + +import java.util.Iterator; + +/** + * Implementation of a Repository to store users on the File System. + * + * Requires a configuration element in the .conf.xml file of the form: + * <repository destinationURL="file://path-to-root-dir-for-repository" + * type="USERS" + * model="SYNCHRONOUS"/> + * Requires a logger called UsersRepository. + * + * + * @version CVS $Revision: 521427 $ + * + */ +public class UsersFileRepository + extends AbstractUsersRepository + implements Configurable, Serviceable, Initializable { + + /** + * Whether 'deep debugging' is turned on. + */ + protected static boolean DEEP_DEBUG = false; + + private Store store; + private ObjectRepository objectRepository; + private static String urlSeparator = "/"; + + /** + * The destination URL used to define the repository. + */ + private String destination; + + /** + * Set the Store + * + * @param store the Store + */ + public void setStore(Store store) { + this.store = store; + } + + /** + * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager) + */ + public void service( final ServiceManager componentManager ) + throws ServiceException { + + try { + setStore((Store)componentManager.lookup( Store.ROLE )); + } catch (Exception e) { + final String message = "Failed to retrieve Store component:" + e.getMessage(); + getLogger().error( message, e ); + throw new ServiceException ("", message, e ); + } + } + + /** + * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) + */ + public void configure( final Configuration configuration ) + throws ConfigurationException { + super.configure(configuration); + destination = configuration.getChild( "destination" ).getAttribute( "URL" ); + + if (!destination.endsWith(urlSeparator)) { + destination += urlSeparator; + } + } + + /** + * @see org.apache.avalon.framework.activity.Initializable#initialize() + */ + public void initialize() + throws Exception { + + try { + //prepare Configurations for object and stream repositories + final DefaultConfiguration objectConfiguration + = new DefaultConfiguration( "repository", + "generated:UsersFileRepository.compose()" ); + + objectConfiguration.setAttribute( "destinationURL", destination ); + objectConfiguration.setAttribute( "type", "OBJECT" ); + objectConfiguration.setAttribute( "model", "SYNCHRONOUS" ); + + objectRepository = (ObjectRepository)store.select( objectConfiguration ); + if (getLogger().isDebugEnabled()) { + StringBuffer logBuffer = + new StringBuffer(192) + .append(this.getClass().getName()) + .append(" created in ") + .append(destination); + getLogger().debug(logBuffer.toString()); + } + } catch (Exception e) { + if (getLogger().isErrorEnabled()) { + getLogger().error("Failed to initialize repository:" + e.getMessage(), e ); + } + throw e; + } + } + + /** + * @see org.apache.james.services.UsersRepository#list() + */ + public Iterator list() { + return objectRepository.list(); + } + + /** + * @see org.apache.james.userrepository.AbstractUsersRepository#doAddUser(org.apache.james.services.User) + */ + protected void doAddUser(User user) { + try { + objectRepository.put(user.getUserName(), user); + } catch (Exception e) { + throw new RuntimeException("Exception caught while storing user: " + e ); + } + } + + /** + * @see org.apache.james.services.UsersRepository#addUser(java.lang.String, java.lang.String) + */ + public boolean addUser(String username, String password) { + User newbie = new DefaultJamesUser(username, "SHA"); + newbie.setPassword(password); + return addUser(newbie); + } + + /** + * @see org.apache.james.services.UsersRepository#getUserByName(java.lang.String) + */ + public synchronized User getUserByName(String name) { + if (ignoreCase) { + name = getRealName(name); + if (name == null ) { + return null; + } + } + if (contains(name)) { + try { + return (User)objectRepository.get(name); + } catch (Exception e) { + throw new RuntimeException("Exception while retrieving user: " + + e.getMessage()); + } + } else { + return null; + } + } + + /** + * @see org.apache.james.services.UsersRepository#getUserByNameCaseInsensitive(java.lang.String) + */ + public User getUserByNameCaseInsensitive(String name) { + String realName = getRealName(name, true); + if (realName == null ) { + return null; + } + return getUserByName(realName); + } + + /** + * Return the real name, given the ignoreCase boolean parameter + */ + public String getRealName(String name, boolean ignoreCase) { + if (ignoreCase) { + Iterator it = list(); + while (it.hasNext()) { + String temp = (String) it.next(); + if (name.equalsIgnoreCase(temp)) { + return temp; + } + } + return null; + } else { + return objectRepository.containsKey(name) ? name : null; + } + } + + /** + * @see org.apache.james.services.UsersRepository#getRealName(java.lang.String) + */ + public String getRealName(String name) { + return getRealName(name, ignoreCase); + } + + /** + * @see org.apache.james.userrepository.AbstractUsersRepository#doUpdateUser(org.apache.james.services.User) + */ + public void doUpdateUser(User user) { + try { + objectRepository.put(user.getUserName(), user); + } catch (Exception e) { + throw new RuntimeException("Exception caught while storing user: " + + e); + } + } + + /** + * @see org.apache.james.services.UsersRepository#removeUser(java.lang.String) + */ + public synchronized void removeUser(String name) { + objectRepository.remove(name); + } + + /** + * @see org.apache.james.services.UsersRepository#contains(java.lang.String) + */ + public boolean contains(String name) { + if (ignoreCase) { + return containsCaseInsensitive(name); + } else { + return objectRepository.containsKey(name); + } + } + + /** + * @see org.apache.james.services.UsersRepository#containsCaseInsensitive(java.lang.String) + */ + public boolean containsCaseInsensitive(String name) { + Iterator it = list(); + while (it.hasNext()) { + if (name.equalsIgnoreCase((String)it.next())) { + return true; + } + } + return false; + } + + /** + * @see org.apache.james.services.UsersRepository#test(java.lang.String, java.lang.String) + */ + public boolean test(String name, String password) { + User user; + try { + user = getUserByName(name); + if (user == null) return false; + } catch (Exception e) { + throw new RuntimeException("Exception retrieving User" + e); + } + return user.verifyPassword(password); + } + + /** + * @see org.apache.james.services.UsersRepository#countUsers() + */ + public int countUsers() { + int count = 0; + for (Iterator it = list(); it.hasNext(); it.next()) { + count++; + } + return count; + } + +} Added: james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersLDAPRepository.java URL: http://svn.apache.org/viewvc/james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersLDAPRepository.java?rev=599566&view=auto ============================================================================== --- james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersLDAPRepository.java (added) +++ james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/UsersLDAPRepository.java Thu Nov 29 12:08:58 2007 @@ -0,0 +1,786 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + + + +package org.apache.james.userrepository; + +import org.apache.avalon.framework.activity.Initializable; +import org.apache.avalon.framework.configuration.Configurable; +import org.apache.avalon.framework.configuration.Configuration; +import org.apache.avalon.framework.configuration.ConfigurationException; +import org.apache.james.services.User; +import org.apache.james.userrepository.AbstractUsersRepository; +import org.apache.james.userrepository.DefaultUser; + +import javax.naming.AuthenticationException; +import javax.naming.NamingEnumeration; +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.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.ModificationItem; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; + +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; + +/** + * Implementation of a Repository to store users. + * + * This clas is a dummy for the proposal! + * + * TODO: Check for aliases (mail attribute) + * + * @version This is $Revision: 521427 $ + */ +public class UsersLDAPRepository + extends AbstractUsersRepository + implements Configurable, Initializable{ + + private DirContext ctx; + + private String LDAPHost; + private String rootNodeDN; + private String rootURL; + private String serverRDN; + private String baseNodeDN; + private String baseURL; + private String mailAddressAttr; + private String identAttr; + private String authType; + private String principal; + private String password; + private String usersDomain; + private String membersAttr; + private boolean manageGroupAttr; + private String groupAttr; + private boolean managePasswordAttr; + private String passwordAttr; + private SearchControls searchControls = new SearchControls(); + + /** + * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) + */ + public void configure(Configuration conf) throws ConfigurationException { + super.configure(conf); + + //TODO: Take care of baseNodeDN + LDAPHost = conf.getChild("LDAPServer").getValue(); + usersDomain = conf.getChild("domain").getValue("localhost"); + rootNodeDN = conf.getChild("LDAPRoot").getValue(); + serverRDN = conf.getChild("ThisServerRDN").getValue(); + mailAddressAttr + = conf.getChild("MailAddressAttribute").getValue(); + identAttr = conf.getChild("IdentityAttribute").getValue(); + authType = conf.getChild("AuthenticationType").getValue(); + principal = conf.getChild("Principal").getValue(); + password = conf.getChild("Password").getValue(); + + membersAttr = conf.getChild("MembersAttribute").getValue(); + manageGroupAttr = conf.getChild("ManageGroupAttribute").getValueAsBoolean( false ); + + // Check if groupAttr is needed + if (manageGroupAttr == true) { + groupAttr = conf.getChild("GroupAttribute").getValue(); + } + + managePasswordAttr = conf.getChild("ManagePasswordAttribute").getValueAsBoolean( false ); + + // Check if passwordAttr is needed + if (managePasswordAttr) { + passwordAttr = conf.getChild("PasswordAttribute").getValue(); + } + } + + public void setServerRoot() { + StringBuffer serverRootBuffer = + new StringBuffer(128) + .append(serverRDN) + .append(", ") + .append(rootNodeDN); + this.setBase(serverRootBuffer.toString()); + } + + public void setBase(String base) { + baseNodeDN = base; + } + + /** + * @see org.apache.avalon.framework.activity.Initializable#initialize() + */ + public void initialize() throws Exception { + //setServerRoot(); + StringBuffer urlBuffer = + new StringBuffer(128) + .append(LDAPHost) + .append("/"); + rootURL = urlBuffer.toString() + rootNodeDN; + baseURL = urlBuffer.toString(); // + baseNodeDN; + + getLogger().info("Creating initial context from " + baseURL); + + Hashtable env = new Hashtable(); + env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(javax.naming.Context.PROVIDER_URL, baseURL); + + env.put(javax.naming.Context.SECURITY_AUTHENTICATION, authType); + env.put(javax.naming.Context.SECURITY_PRINCIPAL, principal); + env.put(javax.naming.Context.SECURITY_CREDENTIALS, password); + + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + + + ctx = new InitialDirContext(env); // Could throw a NamingExcpetion + + + getLogger().info("Initial context initialized from " + baseURL); + } + + + + public String getChildDestination(String childName) { + + String destination = null; + String filter = "cn=" + childName; + SearchControls ctls = new SearchControls(); + + try { + + NamingEnumeration result = ctx.search("", filter, ctls); + + if (result.hasMore()) { + StringBuffer destinationBuffer = + new StringBuffer(128) + .append("cn=") + .append(childName) + .append(", ") + .append(baseNodeDN); + destination = destinationBuffer.toString(); + getLogger().info("Pre-exisisting LDAP node: " + destination); + } else { + Attributes attrs = new BasicAttributes(true); + Attribute objclass = new BasicAttribute("objectclass"); + objclass.add("top"); + objclass.add("rfc822MailGroup"); + attrs.put(objclass); + Attribute cname = new BasicAttribute("cn"); + cname.add(childName); + attrs.put(cname); + Attribute owner = new BasicAttribute("owner"); + owner.add("JAMES-unassigned"); + attrs.put(owner); +/* + ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, authType); + ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, principal); + ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password); +*/ + ctx.createSubcontext("cn=" + childName, attrs); +// ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); + + StringBuffer destinationBuffer = + new StringBuffer(128) + .append("cn=") + .append(childName) + .append(", ") + .append(baseNodeDN); + destination = destinationBuffer.toString(); + getLogger().info("Created new LDAP node: " + destination); + } + } catch (NamingException e) { + getLogger().error("Problem with child nodes " + e.getMessage(), e); + } + + return destination; + } + + /** + * List users in repository. + * + * @return Iterator over a collection of Strings, each being one user in the repository. + */ + public Iterator list() { + return getUsers().iterator(); + } + + /** + * Update the repository with the specified user object. Unsupported for + * this user repository type. + * + * @return false + */ + public boolean addUser(User user) { + return false; + } + + /** + * @see org.apache.james.services.UsersRepository#getUserByName(java.lang.String) + */ + public User getUserByName(String name) { + return new DefaultUser("dummy", "dummy"); + } + + /** + * @see org.apache.james.services.UsersRepository#getUserByNameCaseInsensitive(java.lang.String) + */ + public User getUserByNameCaseInsensitive(String name) { + return getUserByName(name); + } + + /** + * @see org.apache.james.services.UsersRepository#containsCaseInsensitive(java.lang.String) + */ + public boolean containsCaseInsensitive(String name) { + return getUsers().contains(name); + } + + /** + * @see org.apache.james.services.UsersRepository#getRealName(java.lang.String) + */ + public String getRealName(String name) { + return getRealName(name, ignoreCase); + } + + /** + * Return the real name, given the ignoreCase boolean parameter + */ + public String getRealName(String name, boolean ignoreCase) { + Iterator it = list(); + while (it.hasNext()) { + String temp = (String) it.next(); + if (ignoreCase) { + if (name.equalsIgnoreCase(temp)) { + return temp; + } + } else { + if (name.equals(temp)) { + return temp; + } + } + } + return null; + } + + /** + * @see org.apache.james.services.UsersRepository#updateUser(org.apache.james.services.User) + */ + public boolean updateUser(User user) { + return false; + } + + /** + * @see org.apache.james.services.UsersRepository#addUser(java.lang.String, java.lang.String) + */ + public boolean addUser(String username, String password) { + if (!contains(username)) { + addUser(username, password); + return contains(username); + } else { + return false; + } + } + + private void addGroupToUser(String userName) { + String[] attrIDs = {membersAttr}; + + Hashtable env = new Hashtable(); + env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(javax.naming.Context.PROVIDER_URL, rootURL); + + DirContext rootCtx = null; + try { + rootCtx = new InitialDirContext(env); + + String[] returnAttrs = {groupAttr}; + SearchControls ctls = new SearchControls(); + ctls.setReturningAttributes(attrIDs); + ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); + StringBuffer filterBuffer = + new StringBuffer(128) + .append(mailAddressAttr) + .append("=") + .append(userName) + .append("@") + .append(usersDomain); + String filter = filterBuffer.toString(); + + NamingEnumeration enumeration = rootCtx.search("", filter, ctls); + + if (enumeration.hasMore()) { // ie User is in Directory + SearchResult newSr = (SearchResult)enumeration.next(); + String userDN = newSr.getName(); + Attribute servers = rootCtx.getAttributes(userDN, returnAttrs).get(groupAttr); + + + if (servers != null && servers.contains(baseNodeDN)) {//server already registered for user + getLogger().info(baseNodeDN + " already in user's Groups. " ); + //System.out.println(baseNodeDN + " already in user's Groups. "); + + } else { +/* + rootCtx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, authType); + rootCtx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, principal); + rootCtx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password); +*/ + rootCtx.modifyAttributes(userDN, DirContext.ADD_ATTRIBUTE, new BasicAttributes(groupAttr, baseNodeDN, true)); + + //rootCtx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); + getLogger().info(baseNodeDN + " added to user's groups "); + //System.out.println(baseNodeDN + " added to users' groups "); + + } + + } else { + StringBuffer infoBuffer = + new StringBuffer(64) + .append("User ") + .append(userName) + .append(" not in directory."); + getLogger().info(infoBuffer.toString()); + // System.out.println(infoBuffer.toString()); + + } + } catch (NamingException e) { + getLogger().error("Problem adding group to user " + userName); + //System.out.println("Problem adding group to user " + userName); + //System.out.println(e.getMessage()); + //e.printStackTrace(); + } finally { + closeDirContext(rootCtx); + } + } + + /** + * @see org.apache.james.services.UsersRepository#removeUser(java.lang.String) + */ + public synchronized void removeUser(String userName) { + String[] attrIDs = {membersAttr}; + + try { + Attribute members = ctx.getAttributes("", attrIDs).get(membersAttr); + if (members == null) { + System.out.println("UsersLDAPRepository - Null list attribute."); + + } else if (!members.contains(userName)) {//user not here + getLogger().info(userName + " missing from mailGroup. "); + //System.out.println(userName + " missing from mailGroup. "); + + } else { + // First, remove username from mailGroup at baseNode +/* + ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, authType); + ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, principal); + ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password); +*/ + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute(membersAttr, userName)); + + ctx.modifyAttributes("", mods); + + +// ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); + getLogger().info(userName + " removed from mailGroup. "); + //System.out.println(userName + " removed from mailGroup. "); + } + } catch (NamingException e) { + StringBuffer exceptionBuffer = + new StringBuffer(256) + .append("Problem removing user ") + .append(userName) + .append(": ") + .append(e); + getLogger().error(exceptionBuffer.toString()); + //System.out.println("Problem removing user " + userName); + //System.out.println(e.getMessage()); + //e.printStackTrace(); + } + if (manageGroupAttr) { + removeGroupFromUser(userName); + } + + if (managePasswordAttr) { + // not yet implemented + } + + } + + public void removeGroupFromUser(String userName) { + + Hashtable env = new Hashtable(); + env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(javax.naming.Context.PROVIDER_URL, rootURL); + + + DirContext rootCtx = null; + try { + rootCtx = new InitialDirContext(env); + + // Find directory entry + String[] returnAttrs = {groupAttr}; + SearchControls ctls = new SearchControls(); + ctls.setReturningAttributes(returnAttrs); + ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); + StringBuffer filterBuffer = + new StringBuffer(128) + .append(mailAddressAttr) + .append("=") + .append(userName) + .append("@") + .append(usersDomain); + String filter = filterBuffer.toString(); + + NamingEnumeration enumeration = rootCtx.search("", filter, ctls); + + if (enumeration.hasMore()) { // ie User is in Directory + SearchResult newSr = (SearchResult)enumeration.next(); + String userDN = newSr.getName(); + + System.out.println("Found user entry: " + userDN); + + Attribute servers = rootCtx.getAttributes(userDN, returnAttrs).get(groupAttr); + if (servers == null) { //should not happen + getLogger().info("GroupAttribute missing from user: " + userName); + // System.out.println("GroupAttribute missing from user: " + userName ); + + } else if (!servers.contains(baseNodeDN)) {//server not registered for user + getLogger().info(baseNodeDN + " missing from users' Groups. " ); + //System.out.println(baseNodeDN + " missing from users' Groups. "); + + } else { +/* + rootCtx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, authType); + rootCtx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, principal); + rootCtx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password); +*/ + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute(groupAttr, baseNodeDN)); + + rootCtx.modifyAttributes(userDN, mods); + + //rootCtx.modifyAttributes(userDN, DirContext.REPLACE_ATTRIBUTE, changes); + +// rootCtx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); + getLogger().info(baseNodeDN + " removed from users' groups " ); + //System.out.println(baseNodeDN + " removed from users' groups "); + + } + + } else { + StringBuffer infoBuffer = + new StringBuffer(64) + .append("User ") + .append(userName) + .append(" not in directory."); + getLogger().info(infoBuffer.toString()); + //System.out.println(infoBuffer.toString()); + + } + } catch (NamingException e) { + StringBuffer exceptionBuffer = + new StringBuffer(256) + .append("Problem removing user ") + .append(userName) + .append(e); + getLogger().error(exceptionBuffer.toString()); + //System.out.println("Problem removing user " + userName); + //System.out.println(e.getMessage()); + //e.printStackTrace(); + } finally { + closeDirContext(rootCtx); + rootCtx = null; + } + } + + + /** + * @see org.apache.james.services.UsersRepository#contains(java.lang.String) + */ + public boolean contains(String name) { + boolean found = false; + if (ignoreCase) { + if(containsCaseInsensitive(name)) { + found = true; + } + } else { + Iterator it = list(); + + while (it.hasNext()) { + if (name.equals(it.next())) { + found = true; + } + } + } + + if(found) { + StringBuffer infoBuffer = + new StringBuffer(64) + .append("Found ") + .append(name) + .append(" in mailGroup. "); + getLogger().info(infoBuffer.toString()); + return true; + } + return false; + } + + + /** + * @see org.apache.james.services.UsersRepository#test(java.lang.String, java.lang.String) + */ + public boolean test(String name, String testPassword) { + boolean result = false; + boolean foundFlag = false; + String userDN = null; + + try { + String[] returnAttrs = {identAttr, passwordAttr}; + SearchControls ctls = new SearchControls(); + ctls.setReturningAttributes(returnAttrs); + ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); + StringBuffer filterBuffer = + new StringBuffer(128) + .append(mailAddressAttr) + .append("=") + .append(name) + .append("@") + .append(usersDomain); + String filter = filterBuffer.toString(); + + Hashtable env = new Hashtable(); + env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(javax.naming.Context.PROVIDER_URL, rootURL); + DirContext rootCtx = null; + + try { + rootCtx = new InitialDirContext(env); + + NamingEnumeration enumeration = rootCtx.search("", filter, ctls); + if (enumeration.hasMore()) { // ie User is in Directory + SearchResult sr = (SearchResult)enumeration.next(); + String userRDN = sr.getName(); + StringBuffer userDNBuffer = + new StringBuffer(128) + .append(userRDN) + .append(", ") + .append(rootNodeDN); + userDN = userDNBuffer.toString(); + foundFlag = true; + //System.out.println("UserDN is : " + userDN); + } + } finally { + closeDirContext(rootCtx); + } + } catch (Exception e) { + StringBuffer exceptionBuffer = + new StringBuffer(256) + .append("Problem finding user ") + .append(name) + .append(" for password test.") + .append(e); + getLogger().error(exceptionBuffer.toString()); + //e.getMessage(); + //e.printStackTrace(); + } + + if (foundFlag) { // ie User is in Directory + Hashtable env2 = new Hashtable(); + env2.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env2.put(javax.naming.Context.PROVIDER_URL, rootURL); + env2.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); + env2.put(javax.naming.Context.SECURITY_PRINCIPAL, userDN); + env2.put(javax.naming.Context.SECURITY_CREDENTIALS, testPassword); + //System.out.println("Creating initial context from " + baseURL); + + DirContext testCtx = null; + try { + testCtx = new InitialDirContext(env2); + result = true; + + } catch (AuthenticationException ae) { + result = false; + StringBuffer exceptionBuffer = + new StringBuffer(256) + .append("Attempt to authenticate with incorrect password for ") + .append(name) + .append(" : ") + .append(ae); + getLogger().error(exceptionBuffer.toString()); + //System.out.println(exceptionBuffer.toString()); + //System.out.println(ae.getMessage()); + //ae.printStackTrace(); + } catch (Exception e) { + StringBuffer exceptionBuffer = + new StringBuffer(256) + .append("Problem checking password for ") + .append(name) + .append(" : ") + .append(e); + getLogger().error(exceptionBuffer.toString()); + //System.out.println(exceptionBuffer.toString()); + //System.out.println(e.getMessage()); + //e.printStackTrace(); + } finally { + closeDirContext(testCtx); + } + } + return result; + + } + + /** + * @see org.apache.james.services.UsersRepository#countUsers() + */ + public int countUsers() { + return getUsers().size(); + } + + /** + * Disposes of all open directory contexts + * + * @throws Exception if an error is encountered during shutdown + */ + public void dispose() throws Exception { + closeDirContext(ctx); + ctx = null; + } + + private void closeDirContext(DirContext ctx) { + try { + if (ctx != null) { + ctx.close(); + } + } catch (NamingException ne) { + getLogger().warn("UsersLDAPRepository: Unexpected exception encountered while closing directory context: " + ne); + } + } + + + /** + * Adds userName to the MemberAttribute (specified in conf.xml) of this + * node. + * If ManageGroupAttribute (conf.xml) is TRUE then calls addGroupToUser. + */ + protected void doAddUser(User user) { + String userName = user.getUserName(); + + String[] attrIDs = {membersAttr}; + + // First, add username to mailGroup at baseNode + + try { + Attribute members = ctx.getAttributes("", attrIDs).get(membersAttr); + + + if (members != null && members.contains(userName)) {//user already here + StringBuffer infoBuffer = + new StringBuffer(64) + .append("Found ") + .append(userName) + .append(" already in mailGroup. "); + getLogger().info(infoBuffer.toString()); + //System.out.println(infoBuffer.toString()); + + } else { + /* + ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, authType); + ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL, principal); + ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS, password); +*/ + ModificationItem[] mods = new ModificationItem[1]; + mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute(membersAttr, userName)); + + ctx.modifyAttributes("", mods); + +// ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); + StringBuffer infoBuffer = + new StringBuffer(128) + .append(userName) + .append(" added to mailGroup ") + .append(baseNodeDN); + getLogger().info(infoBuffer.toString()); + //System.out.println(infoBuffer.toString()); + } + } catch (NamingException e) { + StringBuffer exceptionBuffer = + new StringBuffer(256) + .append("Problem adding user ") + .append(userName) + .append(" to: ") + .append(baseNodeDN) + .append(e); + getLogger().error(exceptionBuffer.toString()); + } + + // Add attributes to user objects, if necessary + + if (manageGroupAttr) { + addGroupToUser(userName); + } + +// if (managePasswordAttr) { +// String userPassword = (String) attributes; // Not yet implemented +// } + } + + protected void doUpdateUser(User user) { + // Do nothing + } + + /** + * Return a list of all users + * + * @return + */ + private List getUsers() { + List result = new ArrayList(); + String filter = mailAddressAttr + "=*"; + + try { + NamingEnumeration results = ctx.search(rootNodeDN, filter, searchControls); + + while (results != null && results.hasMore()) { + Attributes members = ((SearchResult) results.next()).getAttributes(); + + if (members != null) { + + Attribute attr = members.get(identAttr); + if (attr != null) { + NamingEnumeration e = attr.getAll(); + while (e.hasMore()) { + result.add(e.next()); + } + } + } + } + } catch (NamingException e) { + getLogger().error("Problem listing mailboxes. " + e ); + + } + return result; + } +} + + Added: james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/package.html URL: http://svn.apache.org/viewvc/james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/package.html?rev=599566&view=auto ============================================================================== --- james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/package.html (added) +++ james/server/trunk/user-library/src/main/java/org/apache/james/userrepository/package.html Thu Nov 29 12:08:58 2007 @@ -0,0 +1,21 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +--> +<body> +<p>Implementations of user repositories for use in James.</p> +</body> --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
