You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2008/08/27 16:58:53 UTC
svn commit: r689495 [1/2] - in /mina/ftpserver/trunk:
core/src/main/java/org/apache/ftpserver/config/spring/
core/src/main/java/org/apache/ftpserver/filesystem/
core/src/main/java/org/apache/ftpserver/ftpletcontainer/
core/src/main/java/org/apache/ftps...
Author: ngn
Date: Wed Aug 27 07:58:52 2008
New Revision: 689495
URL: http://svn.apache.org/viewvc?rev=689495&view=rev
Log:
Password encryption now moved to a strategy (FTPSERVER-167)
Improved unit tests for user manager configuration
Added:
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/DefaultFtpletContainer.java (with props)
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/FtpletContainer.java (with props)
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/internal/
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptor.java (with props)
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptor.java (with props)
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PasswordEncryptor.java (with props)
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptor.java (with props)
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/util/LocalizedFtpReply.java (with props)
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/DbUserManagerConfigTest.java (contents, props changed)
- copied, changed from r686637, mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/XmlDbUserManagerConfigTest.java
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/FileUserManagerConfigTest.java (with props)
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTestTemplate.java (with props)
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextDbUserManagerTest.java (with props)
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptorTest.java (with props)
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptorTest.java (with props)
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptorTest.java (with props)
mina/ftpserver/trunk/core/src/test/resources/dbusermanagertest-cleartext-hsql.sql
Removed:
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/XmlDbUserManagerConfigTest.java
mina/ftpserver/trunk/core/src/test/resources/spring-config/config-spring-db-user-manager.xml
Modified:
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/filesystem/NativeFileObject.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManager.java
mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManager.java
mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/ClientTestTemplate.java
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/DbUserManagerTest.java
mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/PropertiesUserManagerTest.java
mina/ftpserver/trunk/core/src/test/resources/dbusermanagertest-hsql.sql
mina/ftpserver/trunk/ftplet-api/pom.xml
mina/ftpserver/trunk/ftplet-api/src/main/java/org/apache/ftpserver/ftplet/User.java
Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java?rev=689495&r1=689494&r2=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/config/spring/UserManagerBeanDefinitionParser.java Wed Aug 27 07:58:52 2008
@@ -20,8 +20,11 @@
package org.apache.ftpserver.config.spring;
import org.apache.ftpserver.ftplet.UserManager;
+import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;
import org.apache.ftpserver.usermanager.DbUserManager;
+import org.apache.ftpserver.usermanager.Md5PasswordEncryptor;
import org.apache.ftpserver.usermanager.PropertiesUserManager;
+import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
@@ -51,12 +54,22 @@
protected void doParse(final Element element,
final ParserContext parserContext,
final BeanDefinitionBuilder builder) {
- if (getBeanClass(element) == PropertiesUserManager.class) {
- builder.addPropertyValue("propFile", element.getAttribute("file"));
- if (StringUtils.hasText(element.getAttribute("encrypt-passwords"))
- && element.getAttribute("encrypt-passwords").equals("true")) {
- builder.addPropertyValue("encryptPasswords", true);
+
+ // common for both user managers
+ if (StringUtils.hasText(element.getAttribute("encrypt-passwords"))) {
+ String encryptionStrategy = element.getAttribute("encrypt-passwords");
+
+ if(encryptionStrategy.equals("true") || encryptionStrategy.equals("md5")) {
+ builder.addPropertyValue("passwordEncryptor", new Md5PasswordEncryptor());
+ } else if(encryptionStrategy.equals("salted")) {
+ builder.addPropertyValue("passwordEncryptor", new SaltedPasswordEncryptor());
+ } else {
+ builder.addPropertyValue("passwordEncryptor", new ClearTextPasswordEncryptor());
}
+ }
+
+ if (getBeanClass(element) == PropertiesUserManager.class) {
+ builder.addPropertyValue("file", element.getAttribute("file"));
builder.setInitMethodName("configure");
} else {
Element dsElm = SpringUtil.getChildElement(element,
Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/filesystem/NativeFileObject.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/filesystem/NativeFileObject.java?rev=689495&r1=689494&r2=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/filesystem/NativeFileObject.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/filesystem/NativeFileObject.java Wed Aug 27 07:58:52 2008
@@ -32,7 +32,10 @@
import org.apache.ftpserver.ftplet.FileObject;
import org.apache.ftpserver.ftplet.User;
+import org.apache.ftpserver.usermanager.BaseUser;
import org.apache.ftpserver.usermanager.WriteRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* This class wraps native file object.
@@ -42,6 +45,8 @@
*/
public class NativeFileObject implements FileObject {
+ private final Logger LOG = LoggerFactory.getLogger(NativeFileObject.class);
+
// the file name with respect to the user root.
// The path separator character will be '/' and
// it will always begin with '/'.
@@ -189,13 +194,19 @@
* Check file write permission.
*/
public boolean hasWritePermission() {
+ LOG.debug("Checking authorization for " + getFullName());
if (user.authorize(new WriteRequest(getFullName())) == null) {
+ LOG.debug("Not authorized");
return false;
}
+ LOG.debug("Checking if file exists");
if (file.exists()) {
+ LOG.debug("Checking can write: " + file.canWrite());
return file.canWrite();
}
+
+ LOG.debug("Authorized");
return true;
}
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/DefaultFtpletContainer.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/DefaultFtpletContainer.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/DefaultFtpletContainer.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/DefaultFtpletContainer.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,206 @@
+/*
+ * 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.ftpserver.ftpletcontainer;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.ftpserver.ftplet.FtpException;
+import org.apache.ftpserver.ftplet.FtpRequest;
+import org.apache.ftpserver.ftplet.FtpSession;
+import org.apache.ftpserver.ftplet.Ftplet;
+import org.apache.ftpserver.ftplet.FtpletContext;
+import org.apache.ftpserver.ftplet.FtpletResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This ftplet calls other ftplet methods and returns appropriate return value.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class DefaultFtpletContainer implements FtpletContainer {
+
+ private final Logger LOG = LoggerFactory
+ .getLogger(DefaultFtpletContainer.class);
+
+ private FtpletContext ftpletContext;
+
+ private Map<String, Ftplet> ftplets = new ConcurrentHashMap<String, Ftplet>();
+
+ public synchronized void dispose() {
+
+ for (Entry<String, Ftplet> entry : ftplets.entrySet()) {
+ try {
+ entry.getValue().destroy();
+ } catch (Exception ex) {
+ LOG.error(entry.getKey() + " :: FtpletHandler.destroy()", ex);
+ }
+ }
+ ftplets.clear();
+ }
+
+ public synchronized void addFtplet(String name, Ftplet ftplet) throws FtpException {
+ if (getFtplet(name) != null) {
+ throw new IllegalArgumentException("Ftplet with name \"" + name
+ + "\" already registred with container");
+ }
+
+ ftplets.put(name, ftplet);
+
+ if(ftpletContext != null) {
+ ftplet.init(ftpletContext);
+ }
+ }
+
+ public synchronized Ftplet removeFtplet(String name) {
+ Ftplet ftplet = ftplets.get(name);
+
+ if (ftplet != null) {
+ ftplets.remove(name);
+ return ftplet;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get Ftplet for the given name.
+ */
+ public synchronized Ftplet getFtplet(String name) {
+ if (name == null) {
+ return null;
+ }
+
+ return ftplets.get(name);
+ }
+
+ public synchronized void init(FtpletContext ftpletContext) throws FtpException {
+ this.ftpletContext = ftpletContext;
+
+ // initialize Ftplets already added
+
+ for (Entry<String, Ftplet> entry : ftplets.entrySet()) {
+ entry.getValue().init(ftpletContext);
+ }
+ }
+
+ /**
+ * @see FtpletContainer#getFtplets()
+ */
+ public synchronized Map<String, Ftplet> getFtplets() {
+ return ftplets;
+ }
+
+ /**
+ * @see FtpletContainer#setFtplets(Map)
+ */
+ public synchronized void setFtplets(Map<String, Ftplet> ftplets) {
+ this.ftplets = ftplets;
+ }
+
+ /**
+ * Destroy all ftplets.
+ */
+ public void destroy() {
+ dispose();
+ }
+
+ /**
+ * Call ftplet onConnect.
+ */
+ public FtpletResult onConnect(FtpSession session) throws FtpException,
+ IOException {
+ FtpletResult retVal = FtpletResult.DEFAULT;
+ for (Entry<String, Ftplet> entry : ftplets.entrySet()) {
+ retVal = entry.getValue().onConnect(session);
+ if (retVal == null) {
+ retVal = FtpletResult.DEFAULT;
+ }
+
+ // proceed only if the return value is FtpletResult.DEFAULT
+ if (retVal != FtpletResult.DEFAULT) {
+ break;
+ }
+ }
+ return retVal;
+ }
+
+ /**
+ * Call ftplet onDisconnect.
+ */
+ public FtpletResult onDisconnect(FtpSession session) throws FtpException,
+ IOException {
+ FtpletResult retVal = FtpletResult.DEFAULT;
+ for (Entry<String, Ftplet> entry : ftplets.entrySet()) {
+
+ retVal = entry.getValue().onDisconnect(session);
+ if (retVal == null) {
+ retVal = FtpletResult.DEFAULT;
+ }
+
+ // proceed only if the return value is FtpletResult.DEFAULT
+ if (retVal != FtpletResult.DEFAULT) {
+ break;
+ }
+ }
+ return retVal;
+ }
+
+ public FtpletResult afterCommand(FtpSession session, FtpRequest request)
+ throws FtpException, IOException {
+ FtpletResult retVal = FtpletResult.DEFAULT;
+ for (Entry<String, Ftplet> entry : ftplets.entrySet()) {
+
+ retVal = entry.getValue().afterCommand(session, request);
+ if (retVal == null) {
+ retVal = FtpletResult.DEFAULT;
+ }
+
+ // proceed only if the return value is FtpletResult.DEFAULT
+ if (retVal != FtpletResult.DEFAULT) {
+ break;
+ }
+ }
+ return retVal;
+ }
+
+ public FtpletResult beforeCommand(FtpSession session, FtpRequest request)
+ throws FtpException, IOException {
+ FtpletResult retVal = FtpletResult.DEFAULT;
+ for (Entry<String, Ftplet> entry : ftplets.entrySet()) {
+
+ retVal = entry.getValue().beforeCommand(session, request);
+ if (retVal == null) {
+ retVal = FtpletResult.DEFAULT;
+ }
+
+ // proceed only if the return value is FtpletResult.DEFAULT
+ if (retVal != FtpletResult.DEFAULT) {
+ break;
+ }
+ }
+ return retVal;
+ }
+
+}
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/DefaultFtpletContainer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/FtpletContainer.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/FtpletContainer.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/FtpletContainer.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/FtpletContainer.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,88 @@
+/*
+ * 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.ftpserver.ftpletcontainer;
+
+import java.util.Map;
+
+import org.apache.ftpserver.ftplet.FtpException;
+import org.apache.ftpserver.ftplet.Ftplet;
+
+/**
+ * Interface describing an Ftplet container. Ftplet containers extend the
+ * {@link Ftplet} interface and forward any events to the Ftplets hosted by the
+ * container.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface FtpletContainer extends Ftplet {
+
+ /**
+ * Add an {@link Ftplet} to the container.
+ *
+ * @param name
+ * The name of the Ftplet to be added
+ * @param ftplet
+ * The Ftplet
+ * @throws FtpException
+ * @throws IllegalArgumentException
+ * If an Ftplet with the same name already exist within the
+ * container
+ */
+ void addFtplet(String name, Ftplet ftplet) throws FtpException;
+
+ /**
+ * Remove the {@link Ftplet} identified by the name (as provided in the
+ * {@link #addFtplet(String, Ftplet)} method.
+ *
+ * @param name
+ * The name of the Ftplet to be removed
+ * @return The removed Ftplet if found, or null if the name is unknown to
+ * the container.
+ */
+ Ftplet removeFtplet(String name);
+
+ /**
+ * Retrive the {@link Ftplet} identified by the name (as provided in the
+ * {@link #addFtplet(String, Ftplet)} method.
+ *
+ * @param name
+ * The name of the Ftplet to retrive
+ * @return The Ftplet if found, or null if the name is unknown to the
+ * container.
+ */
+ Ftplet getFtplet(String name);
+
+ /**
+ * Retrive all Ftplets registered with this container
+ *
+ * @return A map of all Ftplets with their name as the key
+ */
+ Map<String, Ftplet> getFtplets();
+
+ /**
+ * Set the Ftplets for this container. Will remove all previously registred
+ * Ftplets in this container
+ *
+ * @param ftplets
+ * A map of all Ftplets with their name as the key
+ */
+ void setFtplets(Map<String, Ftplet> ftplets);
+}
\ No newline at end of file
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/ftpletcontainer/FtpletContainer.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptor.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptor.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptor.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptor.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,54 @@
+/*
+ * 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.ftpserver.usermanager;
+
+
+
+/**
+ * Password encryptor that does no encryption, that is, keps the
+ * password in clear text
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class ClearTextPasswordEncryptor implements PasswordEncryptor {
+
+ /**
+ * Returns the clear text password
+ */
+ public String encrypt(String password) {
+ return password;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean matches(String passwordToCheck, String storedPassword) {
+ if(storedPassword == null) {
+ throw new NullPointerException("storedPassword can not be null");
+ }
+ if(passwordToCheck == null) {
+ throw new NullPointerException("passwordToCheck can not be null");
+ }
+
+ return passwordToCheck.equals(storedPassword);
+ }
+
+}
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/ClearTextPasswordEncryptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManager.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManager.java?rev=689495&r1=689494&r2=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManager.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/DbUserManager.java Wed Aug 27 07:58:52 2008
@@ -75,6 +75,8 @@
// used for lazy init.
private boolean configured = false;
+ private PasswordEncryptor passwordEncryptor = new Md5PasswordEncryptor();
+
/**
* Retrive the data source used by the user manager
*
@@ -428,7 +430,7 @@
// create sql query
HashMap<String, Object> map = new HashMap<String, Object>();
map.put(ATTR_LOGIN, escapeString(user.getName()));
- map.put(ATTR_PASSWORD, escapeString(getPassword(user)));
+ map.put(ATTR_PASSWORD, escapeString(passwordEncryptor.encrypt(user.getPassword())));
String home = user.getHomeDirectory();
if (home == null) {
@@ -649,64 +651,6 @@
}
/**
- * Get user password.
- *
- * <pre>
- * If the password value is not null
- * password = new password
- * else
- * if user does exist
- * password = old password
- * else
- * password = ""
- * </pre>
- */
- private synchronized String getPassword(User user) throws SQLException {
-
- String password = user.getPassword();
- if (password != null) {
- return password;
- }
-
- // create sql query
- HashMap<String, Object> map = new HashMap<String, Object>();
- map.put(ATTR_LOGIN, escapeString(user.getName()));
- String sql = StringUtils.replaceString(selectUserStmt, map);
- LOG.info(sql);
-
- // execute query
- Statement stmt = null;
- ResultSet rs = null;
- try {
- stmt = createConnection().createStatement();
- rs = stmt.executeQuery(sql);
- if (rs.next()) {
- password = rs.getString(ATTR_PASSWORD);
- }
- } finally {
- if (rs != null) {
- try {
- rs.close();
- } catch (Exception ex) {
- LOG.error("DbUserManager.getPassword()", ex);
- }
- }
- if (stmt != null) {
- try {
- stmt.close();
- } catch (Exception ex) {
- LOG.error("DbUserManager.getPassword()", ex);
- }
- }
- }
-
- if (password == null) {
- password = "";
- }
- return password;
- }
-
- /**
* User authentication.
*/
public synchronized User authenticate(Authentication authentication)
@@ -734,7 +678,6 @@
// create the sql query
HashMap<String, Object> map = new HashMap<String, Object>();
map.put(ATTR_LOGIN, escapeString(user));
- map.put(ATTR_PASSWORD, escapeString(password));
String sql = StringUtils.replaceString(authenticateStmt, map);
LOG.info(sql);
@@ -743,7 +686,13 @@
rs = stmt.executeQuery(sql);
if (rs.next()) {
try {
- return getUserByName(user);
+ String storedPassword = rs.getString(ATTR_PASSWORD);
+ if(passwordEncryptor.matches(password, storedPassword)) {
+ return getUserByName(user);
+ } else {
+ throw new AuthenticationFailedException(
+ "Authentication failed");
+ }
} catch (FtpException e) {
throw new AuthenticationFailedException(
"Authentication failed", e);
@@ -819,4 +768,24 @@
}
return valBuf.toString();
}
+
+
+
+ /**
+ * Retrieve the password encryptor used for this user manager
+ * @return The password encryptor. Default to {@link Md5PasswordEncryptor}
+ * if no other has been provided
+ */
+ public PasswordEncryptor getPasswordEncryptor() {
+ return passwordEncryptor;
+ }
+
+
+ /**
+ * Set the password encryptor to use for this user manager
+ * @param passwordEncryptor The password encryptor
+ */
+ public void setPasswordEncryptor(PasswordEncryptor passwordEncryptor) {
+ this.passwordEncryptor = passwordEncryptor;
+ }
}
\ No newline at end of file
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptor.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptor.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptor.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptor.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,55 @@
+/*
+ * 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.ftpserver.usermanager;
+
+import org.apache.ftpserver.util.EncryptUtils;
+
+
+/**
+ * Password encryptor that hashes the password using MD5. Please note that this form
+ * of encryption is sensitive to lookup attacks.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class Md5PasswordEncryptor implements PasswordEncryptor {
+
+ /**
+ * Hashes the password using MD5
+ */
+ public String encrypt(String password) {
+ return EncryptUtils.encryptMD5(password);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean matches(String passwordToCheck, String storedPassword) {
+ if(storedPassword == null) {
+ throw new NullPointerException("storedPassword can not be null");
+ }
+ if(passwordToCheck == null) {
+ throw new NullPointerException("passwordToCheck can not be null");
+ }
+
+ return encrypt(passwordToCheck).equalsIgnoreCase(storedPassword);
+ }
+
+}
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/Md5PasswordEncryptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PasswordEncryptor.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PasswordEncryptor.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PasswordEncryptor.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PasswordEncryptor.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,47 @@
+/*
+ * 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.ftpserver.usermanager;
+
+
+/**
+ * Strategy used for encrypting and matching encrypted passwords.
+ * The purpose is to make the password encryption possible to extend.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public interface PasswordEncryptor {
+
+ /**
+ * Encrypts the password
+ * @param password The clear text password
+ * @return The encrypted password
+ */
+ String encrypt(String password);
+
+ /**
+ * Matches an encrypted password with that stored
+ * @param passwordToCheck The encrypted password to check
+ * @param storedPassword The stored password
+ * @return true if the password match
+ */
+ boolean matches(String passwordToCheck, String storedPassword);
+
+}
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PasswordEncryptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManager.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManager.java?rev=689495&r1=689494&r2=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManager.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/PropertiesUserManager.java Wed Aug 27 07:58:52 2008
@@ -36,7 +36,6 @@
import org.apache.ftpserver.ftplet.FtpException;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.util.BaseProperties;
-import org.apache.ftpserver.util.EncryptUtils;
import org.apache.ftpserver.util.IoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,9 +60,18 @@
private File userDataFile = new File("./res/user.gen");
- private boolean isPasswordEncrypt = true;
-
private boolean isConfigured = false;
+
+ private PasswordEncryptor passwordEncryptor = new Md5PasswordEncryptor();
+
+
+ /**
+ * Retrieve the file used to load and store users
+ * @return The file
+ */
+ public File getFile() {
+ return userDataFile;
+ }
/**
* Set the file used to store and read users. Must be set before
@@ -72,7 +80,7 @@
* @param propFile
* A file containing users
*/
- public void setPropFile(File propFile) {
+ public void setFile(File propFile) {
if (isConfigured) {
throw new IllegalStateException("Must be called before configure()");
}
@@ -80,40 +88,27 @@
this.userDataFile = propFile;
}
+
/**
- * If true is returned, passwords will be stored as hashes rather than in
- * clear text. Default is true.
- *
- * @return True if passwords are stored as hashes.
- */
- public boolean isEncryptPassword() {
- return isPasswordEncrypt;
+ * Retrieve the password encryptor used for this user manager
+ * @return The password encryptor. Default to {@link Md5PasswordEncryptor}
+ * if no other has been provided
+ */
+ public PasswordEncryptor getPasswordEncryptor() {
+ return passwordEncryptor;
}
- /**
- * If set to true, passwords will be stored as a hash to ensure that it can
- * not be retrived from the user file. Must be set before
- * {@link #configure()} is called.
- *
- * @param encryptPassword
- * True to store a hash of the passwords, false to store the
- * passwords in clear text.
- */
- public void setEncryptPasswords(boolean encryptPassword) {
- if (isConfigured) {
- throw new IllegalStateException("Must be called before configure()");
- }
-
- this.isPasswordEncrypt = encryptPassword;
- }
/**
- * @deprecated Use {@link #setEncryptPasswords(boolean)}
+ * Set the password encryptor to use for this user manager
+ * @param passwordEncryptor The password encryptor
*/
- public void setPropPasswordEncrypt(boolean encryptPassword) {
- setEncryptPasswords(encryptPassword);
+ public void setPasswordEncryptor(PasswordEncryptor passwordEncryptor) {
+ this.passwordEncryptor = passwordEncryptor;
}
+
+
/**
* Lazy init the user manager
*/
@@ -303,14 +298,9 @@
String password = usr.getPassword();
if (password != null) {
- if (isPasswordEncrypt) {
- password = EncryptUtils.encryptMD5(password);
- }
+ password = passwordEncryptor.encrypt(password);
} else {
- String blankPassword = "";
- if (isPasswordEncrypt) {
- blankPassword = EncryptUtils.encryptMD5("");
- }
+ String blankPassword = passwordEncryptor.encrypt("");
if (doesExist(name)) {
String key = PREFIX + name + '.' + ATTR_PASSWORD;
@@ -424,12 +414,15 @@
password = "";
}
- String passVal = userDataProp.getProperty(PREFIX + user + '.'
+ String storedPassword = userDataProp.getProperty(PREFIX + user + '.'
+ ATTR_PASSWORD);
- if (isPasswordEncrypt) {
- password = EncryptUtils.encryptMD5(password);
+
+ if(storedPassword == null) {
+ // user does not exist
+ throw new AuthenticationFailedException("Authentication failed");
}
- if (password.equals(passVal)) {
+
+ if (passwordEncryptor.matches(password, storedPassword)) {
return getUserByName(user);
} else {
throw new AuthenticationFailedException("Authentication failed");
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptor.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptor.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptor.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptor.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,85 @@
+/*
+ * 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.ftpserver.usermanager;
+
+import java.security.SecureRandom;
+
+import org.apache.ftpserver.util.EncryptUtils;
+
+/**
+ * Password encryptor that hashes a salt together with the password using MD5.
+ * Using a salt protects against birthday attacks.
+ * The hashing is also made in iterations, making lookup attacks much harder.
+ *
+ * The algorithm is based on the principles described in
+ * http://www.jasypt.org/howtoencryptuserpasswords.html
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class SaltedPasswordEncryptor implements PasswordEncryptor {
+
+ private SecureRandom rnd = new SecureRandom();
+
+ private static final int MAX_SEED = 99999999;
+ private static final int HASH_ITERATIONS = 1000;
+
+ private String encrypt(String password, String salt) {
+ String hash = salt + password;
+ for (int i = 0; i < HASH_ITERATIONS; i++) {
+ hash = EncryptUtils.encryptMD5(hash);
+ }
+ return salt + ":" + hash;
+ }
+
+ /**
+ * Encrypts the password using a salt concatenated with the password
+ * and a series of MD5 steps.
+ */
+ public String encrypt(String password) {
+ String seed = Integer.toString(rnd.nextInt(MAX_SEED));
+
+ return encrypt(password, seed);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean matches(String passwordToCheck, String storedPassword) {
+ if (storedPassword == null) {
+ throw new NullPointerException("storedPassword can not be null");
+ }
+ if (passwordToCheck == null) {
+ throw new NullPointerException("passwordToCheck can not be null");
+ }
+
+ // look for divider for hash
+ int divider = storedPassword.indexOf(':');
+
+ if(divider < 1) {
+ throw new IllegalArgumentException("stored password does not contain salt");
+ }
+
+ String storedSalt = storedPassword.substring(0, divider);
+
+ return encrypt(passwordToCheck, storedSalt).equalsIgnoreCase(storedPassword);
+ }
+
+}
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/usermanager/SaltedPasswordEncryptor.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/util/LocalizedFtpReply.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/util/LocalizedFtpReply.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/util/LocalizedFtpReply.java (added)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/util/LocalizedFtpReply.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,499 @@
+/*
+ * 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.ftpserver.util;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import org.apache.ftpserver.ftplet.DefaultFtpReply;
+import org.apache.ftpserver.ftplet.FileSystemView;
+import org.apache.ftpserver.ftplet.FtpReply;
+import org.apache.ftpserver.ftplet.FtpRequest;
+import org.apache.ftpserver.ftplet.FtpStatistics;
+import org.apache.ftpserver.interfaces.FtpIoSession;
+import org.apache.ftpserver.interfaces.FtpServerContext;
+import org.apache.ftpserver.interfaces.MessageResource;
+
+/**
+ * FTP reply translator.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class LocalizedFtpReply extends DefaultFtpReply {
+
+ private static final String CLIENT_ACCESS_TIME = "client.access.time";
+
+ private static final String CLIENT_CON_TIME = "client.con.time";
+
+ private static final String CLIENT_DIR = "client.dir";
+
+ private static final String CLIENT_HOME = "client.home";
+
+ private static final String CLIENT_IP = "client.ip";
+
+ private static final String CLIENT_LOGIN_NAME = "client.login.name";
+
+ private static final String CLIENT_LOGIN_TIME = "client.login.time";
+
+ private static final String OUTPUT_CODE = "output.code";
+
+ private static final String OUTPUT_MSG = "output.msg";
+
+ private static final String REQUEST_ARG = "request.arg";
+
+ private static final String REQUEST_CMD = "request.cmd";
+
+ private static final String REQUEST_LINE = "request.line";
+
+ private static final String SERVER_IP = "server.ip";
+
+ private static final String SERVER_PORT = "server.port";
+
+ private static final String STAT_CON_CURR = "stat.con.curr";
+
+ private static final String STAT_CON_TOTAL = "stat.con.total";
+
+ private static final String STAT_DIR_CREATE_COUNT = "stat.dir.create.count";
+
+ private static final String STAT_DIR_DELETE_COUNT = "stat.dir.delete.count";
+
+ private static final String STAT_FILE_DELETE_COUNT = "stat.file.delete.count";
+
+ private static final String STAT_FILE_DOWNLOAD_BYTES = "stat.file.download.bytes";
+
+ private static final String STAT_FILE_DOWNLOAD_COUNT = "stat.file.download.count";
+
+ private static final String STAT_FILE_UPLOAD_BYTES = "stat.file.upload.bytes";
+
+ private static final String STAT_FILE_UPLOAD_COUNT = "stat.file.upload.count";
+
+ private static final String STAT_LOGIN_ANON_CURR = "stat.login.anon.curr";
+
+ private static final String STAT_LOGIN_ANON_TOTAL = "stat.login.anon.total";
+
+ private static final String STAT_LOGIN_CURR = "stat.login.curr";
+
+ private static final String STAT_LOGIN_TOTAL = "stat.login.total";
+
+ private static final String STAT_START_TIME = "stat.start.time";
+
+ public static FtpReply translate(FtpIoSession session, FtpRequest request,
+ FtpServerContext context, int code, String subId, String basicMsg) {
+ String msg = translateMessage(session, request, context, code, subId,
+ basicMsg);
+
+ return new LocalizedFtpReply(code, msg);
+ }
+
+ private static String translateMessage(FtpIoSession session,
+ FtpRequest request, FtpServerContext context, int code,
+ String subId, String basicMsg) {
+ MessageResource resource = context.getMessageResource();
+ String lang = session.getLanguage();
+
+ String msg = null;
+ if (resource != null) {
+ msg = resource.getMessage(code, subId, lang);
+ }
+ if (msg == null) {
+ msg = "";
+ }
+ msg = replaceVariables(session, request, context, code, basicMsg, msg);
+
+ return msg;
+ }
+
+ /**
+ * Replace server variables.
+ */
+ private static String replaceVariables(FtpIoSession session,
+ FtpRequest request, FtpServerContext context, int code,
+ String basicMsg, String str) {
+
+ int startIndex = 0;
+ int openIndex = str.indexOf('{', startIndex);
+ if (openIndex == -1) {
+ return str;
+ }
+
+ int closeIndex = str.indexOf('}', startIndex);
+ if ((closeIndex == -1) || (openIndex > closeIndex)) {
+ return str;
+ }
+
+ StringBuffer sb = new StringBuffer(128);
+ sb.append(str.substring(startIndex, openIndex));
+ while (true) {
+ String varName = str.substring(openIndex + 1, closeIndex);
+ sb.append(getVariableValue(session, request, context, code,
+ basicMsg, varName));
+
+ startIndex = closeIndex + 1;
+ openIndex = str.indexOf('{', startIndex);
+ if (openIndex == -1) {
+ sb.append(str.substring(startIndex));
+ break;
+ }
+
+ closeIndex = str.indexOf('}', startIndex);
+ if ((closeIndex == -1) || (openIndex > closeIndex)) {
+ sb.append(str.substring(startIndex));
+ break;
+ }
+ sb.append(str.substring(startIndex, openIndex));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Get the variable value.
+ */
+ private static String getVariableValue(FtpIoSession session,
+ FtpRequest request, FtpServerContext context, int code,
+ String basicMsg, String varName) {
+
+ String varVal = null;
+
+ // all output variables
+ if (varName.startsWith("output.")) {
+ varVal = getOutputVariableValue(session, code, basicMsg, varName);
+ }
+
+ // all server variables
+ else if (varName.startsWith("server.")) {
+ varVal = getServerVariableValue(session, varName);
+ }
+
+ // all request variables
+ else if (varName.startsWith("request.")) {
+ varVal = getRequestVariableValue(session, request, varName);
+ }
+
+ // all statistical variables
+ else if (varName.startsWith("stat.")) {
+ varVal = getStatisticalVariableValue(session, context, varName);
+ }
+
+ // all client variables
+ else if (varName.startsWith("client.")) {
+ varVal = getClientVariableValue(session, varName);
+ }
+
+ if (varVal == null) {
+ varVal = "";
+ }
+ return varVal;
+ }
+
+ /**
+ * Get client variable value.
+ */
+ private static String getClientVariableValue(FtpIoSession session,
+ String varName) {
+
+ String varVal = null;
+
+ // client ip
+ if (varName.equals(CLIENT_IP)) {
+ if (session.getRemoteAddress() instanceof InetSocketAddress) {
+ InetSocketAddress remoteSocketAddress = (InetSocketAddress) session
+ .getRemoteAddress();
+ varVal = remoteSocketAddress.getAddress().getHostAddress();
+ }
+
+ }
+
+ // client connection time
+ else if (varName.equals(CLIENT_CON_TIME)) {
+ varVal = DateUtils.getISO8601Date(session.getCreationTime());
+ }
+
+ // client login name
+ else if (varName.equals(CLIENT_LOGIN_NAME)) {
+ if (session.getUser() != null) {
+ varVal = session.getUser().getName();
+ }
+ }
+
+ // client login time
+ else if (varName.equals(CLIENT_LOGIN_TIME)) {
+ varVal = DateUtils.getISO8601Date(session.getLoginTime().getTime());
+ }
+
+ // client last access time
+ else if (varName.equals(CLIENT_ACCESS_TIME)) {
+ varVal = DateUtils.getISO8601Date(session.getLastAccessTime()
+ .getTime());
+ }
+
+ // client home
+ else if (varName.equals(CLIENT_HOME)) {
+ varVal = session.getUser().getHomeDirectory();
+ }
+
+ // client directory
+ else if (varName.equals(CLIENT_DIR)) {
+ FileSystemView fsView = session.getFileSystemView();
+ if (fsView != null) {
+ try {
+ varVal = fsView.getCurrentDirectory().getFullName();
+ } catch (Exception ex) {
+ varVal = "";
+ }
+ }
+ }
+ return varVal;
+ }
+
+ /**
+ * Get output variable value.
+ */
+ private static String getOutputVariableValue(FtpIoSession session,
+ int code, String basicMsg, String varName) {
+ String varVal = null;
+
+ // output code
+ if (varName.equals(OUTPUT_CODE)) {
+ varVal = String.valueOf(code);
+ }
+
+ // output message
+ else if (varName.equals(OUTPUT_MSG)) {
+ varVal = basicMsg;
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get request variable value.
+ */
+ private static String getRequestVariableValue(FtpIoSession session,
+ FtpRequest request, String varName) {
+
+ String varVal = null;
+
+ if (request == null) {
+ return "";
+ }
+
+ // request line
+ if (varName.equals(REQUEST_LINE)) {
+ varVal = request.getRequestLine();
+ }
+
+ // request command
+ else if (varName.equals(REQUEST_CMD)) {
+ varVal = request.getCommand();
+ }
+
+ // request argument
+ else if (varName.equals(REQUEST_ARG)) {
+ varVal = request.getArgument();
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get server variable value.
+ */
+ private static String getServerVariableValue(FtpIoSession session,
+ String varName) {
+
+ String varVal = null;
+
+ SocketAddress localSocketAddress = session.getLocalAddress();
+
+ if (localSocketAddress instanceof InetSocketAddress) {
+ InetSocketAddress localInetSocketAddress = (InetSocketAddress) localSocketAddress;
+ // server address
+ if (varName.equals(SERVER_IP)) {
+
+ InetAddress addr = localInetSocketAddress.getAddress();
+
+ if (addr != null) {
+ varVal = addr.getHostAddress();
+ }
+ }
+
+ // server port
+ else if (varName.equals(SERVER_PORT)) {
+ varVal = String.valueOf(localInetSocketAddress.getPort());
+ }
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get statistical connection variable value.
+ */
+ private static String getStatisticalConnectionVariableValue(
+ FtpIoSession session, FtpServerContext context, String varName) {
+ String varVal = null;
+ FtpStatistics stat = context.getFtpStatistics();
+
+ // total connection number
+ if (varName.equals(STAT_CON_TOTAL)) {
+ varVal = String.valueOf(stat.getTotalConnectionNumber());
+ }
+
+ // current connection number
+ else if (varName.equals(STAT_CON_CURR)) {
+ varVal = String.valueOf(stat.getCurrentConnectionNumber());
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get statistical directory variable value.
+ */
+ private static String getStatisticalDirectoryVariableValue(
+ FtpIoSession session, FtpServerContext context, String varName) {
+ String varVal = null;
+ FtpStatistics stat = context.getFtpStatistics();
+
+ // total directory created
+ if (varName.equals(STAT_DIR_CREATE_COUNT)) {
+ varVal = String.valueOf(stat.getTotalDirectoryCreated());
+ }
+
+ // total directory removed
+ else if (varName.equals(STAT_DIR_DELETE_COUNT)) {
+ varVal = String.valueOf(stat.getTotalDirectoryRemoved());
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get statistical file variable value.
+ */
+ private static String getStatisticalFileVariableValue(FtpIoSession session,
+ FtpServerContext context, String varName) {
+ String varVal = null;
+ FtpStatistics stat = context.getFtpStatistics();
+
+ // total number of file upload
+ if (varName.equals(STAT_FILE_UPLOAD_COUNT)) {
+ varVal = String.valueOf(stat.getTotalUploadNumber());
+ }
+
+ // total bytes uploaded
+ else if (varName.equals(STAT_FILE_UPLOAD_BYTES)) {
+ varVal = String.valueOf(stat.getTotalUploadSize());
+ }
+
+ // total number of file download
+ else if (varName.equals(STAT_FILE_DOWNLOAD_COUNT)) {
+ varVal = String.valueOf(stat.getTotalDownloadNumber());
+ }
+
+ // total bytes downloaded
+ else if (varName.equals(STAT_FILE_DOWNLOAD_BYTES)) {
+ varVal = String.valueOf(stat.getTotalDownloadSize());
+ }
+
+ // total number of files deleted
+ else if (varName.equals(STAT_FILE_DELETE_COUNT)) {
+ varVal = String.valueOf(stat.getTotalDeleteNumber());
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get statistical login variable value.
+ */
+ private static String getStatisticalLoginVariableValue(
+ FtpIoSession session, FtpServerContext context, String varName) {
+ String varVal = null;
+ FtpStatistics stat = context.getFtpStatistics();
+
+ // total login number
+ if (varName.equals(STAT_LOGIN_TOTAL)) {
+ varVal = String.valueOf(stat.getTotalLoginNumber());
+ }
+
+ // current login number
+ else if (varName.equals(STAT_LOGIN_CURR)) {
+ varVal = String.valueOf(stat.getCurrentLoginNumber());
+ }
+
+ // total anonymous login number
+ else if (varName.equals(STAT_LOGIN_ANON_TOTAL)) {
+ varVal = String.valueOf(stat.getTotalAnonymousLoginNumber());
+ }
+
+ // current anonymous login number
+ else if (varName.equals(STAT_LOGIN_ANON_CURR)) {
+ varVal = String.valueOf(stat.getCurrentAnonymousLoginNumber());
+ }
+
+ return varVal;
+ }
+
+ /**
+ * Get statistical variable value.
+ */
+ private static String getStatisticalVariableValue(FtpIoSession session,
+ FtpServerContext context, String varName) {
+
+ String varVal = null;
+ FtpStatistics stat = context.getFtpStatistics();
+
+ // server start time
+ if (varName.equals(STAT_START_TIME)) {
+ varVal = DateUtils.getISO8601Date(stat.getStartTime().getTime());
+ }
+
+ // connection statistical variables
+ else if (varName.startsWith("stat.con")) {
+ varVal = getStatisticalConnectionVariableValue(session, context,
+ varName);
+ }
+
+ // login statistical variables
+ else if (varName.startsWith("stat.login.")) {
+ varVal = getStatisticalLoginVariableValue(session, context, varName);
+ }
+
+ // file statistical variable
+ else if (varName.startsWith("stat.file")) {
+ varVal = getStatisticalFileVariableValue(session, context, varName);
+ }
+
+ // directory statistical variable
+ else if (varName.startsWith("stat.dir.")) {
+ varVal = getStatisticalDirectoryVariableValue(session, context,
+ varName);
+ }
+
+ return varVal;
+ }
+
+ private LocalizedFtpReply(int code, String message) {
+ super(code, message);
+ }
+}
Propchange: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/util/LocalizedFtpReply.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd?rev=689495&r1=689494&r2=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd (original)
+++ mina/ftpserver/trunk/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd Wed Aug 27 07:58:52 2008
@@ -1,30 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!--
- 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. -->
-
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
- targetNamespace="http://mina.apache.org/ftpserver/spring/v1"
- xmlns="http://mina.apache.org/ftpserver/spring/v1"
- xmlns:beans="http://www.springframework.org/schema/beans">
+ <!--
+ 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.
+ -->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" targetNamespace="http://mina.apache.org/ftpserver/spring/v1"
+ xmlns="http://mina.apache.org/ftpserver/spring/v1" xmlns:beans="http://www.springframework.org/schema/beans">
<!-- Import the Spring beans XML schema -->
<xs:import namespace="http://www.springframework.org/schema/beans"
- schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"/>
+ schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd" />
<!-- The main entry point, used for setting up an entire FTP server -->
<xs:element name="server">
@@ -33,30 +28,30 @@
<xs:element minOccurs="0" name="listeners">
<xs:complexType>
<xs:choice minOccurs="1" maxOccurs="unbounded">
- <xs:element ref="nio-listener"/>
- <xs:element ref="listener"/>
+ <xs:element ref="nio-listener" />
+ <xs:element ref="listener" />
</xs:choice>
</xs:complexType>
</xs:element>
- <xs:element minOccurs="0" ref="ftplets"/>
+ <xs:element minOccurs="0" ref="ftplets" />
<xs:choice minOccurs="0" maxOccurs="1">
- <xs:element minOccurs="0" ref="file-user-manager"/>
- <xs:element minOccurs="0" ref="db-user-manager"/>
- <xs:element minOccurs="0" ref="user-manager"/>
+ <xs:element minOccurs="0" ref="file-user-manager" />
+ <xs:element minOccurs="0" ref="db-user-manager" />
+ <xs:element minOccurs="0" ref="user-manager" />
</xs:choice>
<xs:choice minOccurs="0" maxOccurs="1">
- <xs:element minOccurs="0" ref="native-filesystem"/>
- <xs:element minOccurs="0" ref="filesystem"/>
+ <xs:element minOccurs="0" ref="native-filesystem" />
+ <xs:element minOccurs="0" ref="filesystem" />
</xs:choice>
- <xs:element minOccurs="0" ref="commands"/>
- <xs:element minOccurs="0" ref="messages"/>
+ <xs:element minOccurs="0" ref="commands" />
+ <xs:element minOccurs="0" ref="messages" />
</xs:sequence>
- <xs:attribute name="id" type="xs:ID"/>
- <xs:attribute name="max-logins" type="xs:int"/>
- <xs:attribute name="max-anon-logins" type="xs:int"/>
- <xs:attribute name="anon-enabled" type="xs:boolean"/>
- <xs:attribute name="max-login-failures" type="xs:int"/>
- <xs:attribute name="login-failure-delay" type="xs:int"/>
+ <xs:attribute name="id" type="xs:ID" />
+ <xs:attribute name="max-logins" type="xs:int" />
+ <xs:attribute name="max-anon-logins" type="xs:int" />
+ <xs:attribute name="anon-enabled" type="xs:boolean" />
+ <xs:attribute name="max-login-failures" type="xs:int" />
+ <xs:attribute name="login-failure-delay" type="xs:int" />
</xs:complexType>
</xs:element>
@@ -66,41 +61,40 @@
<xs:sequence>
<xs:element name="keystore">
<xs:complexType>
- <xs:attribute name="file" use="required"/>
- <xs:attribute name="password" use="required"/>
- <xs:attribute name="type"/>
- <xs:attribute name="algorithm"/>
- <xs:attribute name="key-alias"/>
- <xs:attribute name="key-password"/>
+ <xs:attribute name="file" use="required" />
+ <xs:attribute name="password" use="required" />
+ <xs:attribute name="type" />
+ <xs:attribute name="algorithm" />
+ <xs:attribute name="key-alias" />
+ <xs:attribute name="key-password" />
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="truststore">
<xs:complexType>
- <xs:attribute name="file" use="required"/>
- <xs:attribute name="password"/>
- <xs:attribute name="type"/>
- <xs:attribute name="algorithm"/>
+ <xs:attribute name="file" use="required" />
+ <xs:attribute name="password" />
+ <xs:attribute name="type" />
+ <xs:attribute name="algorithm" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="client-authentication">
- <xs:simpleType>
- <xs:restriction base="xs:string">
- <xs:enumeration value="NEED" />
- <xs:enumeration value="WANT" />
- <xs:enumeration value="NONE" />
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
-
- <xs:attribute name="enabled-ciphersuites" type="xs:string"/>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="NEED" />
+ <xs:enumeration value="WANT" />
+ <xs:enumeration value="NONE" />
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="enabled-ciphersuites" type="xs:string" />
<xs:attribute name="protocol">
- <xs:simpleType>
- <xs:restriction base="xs:string">
- <xs:enumeration value="SSL" />
- <xs:enumeration value="TLS" />
- </xs:restriction>
- </xs:simpleType>
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="SSL" />
+ <xs:enumeration value="TLS" />
+ </xs:restriction>
+ </xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
@@ -109,43 +103,42 @@
<xs:element name="nio-listener">
<xs:complexType>
<xs:sequence>
- <xs:element minOccurs="0" ref="ssl"/>
+ <xs:element minOccurs="0" ref="ssl" />
<xs:element minOccurs="0" name="data-connection">
<xs:complexType>
<xs:sequence>
- <xs:element minOccurs="0" ref="ssl"/>
+ <xs:element minOccurs="0" ref="ssl" />
<xs:element minOccurs="0" name="active">
<xs:complexType>
- <xs:attribute name="enabled" type="xs:boolean"/>
- <xs:attribute name="local-address"/>
- <xs:attribute name="local-port" type="xs:int"/>
- <xs:attribute name="ip-check" type="xs:boolean"/>
+ <xs:attribute name="enabled" type="xs:boolean" />
+ <xs:attribute name="local-address" />
+ <xs:attribute name="local-port" type="xs:int" />
+ <xs:attribute name="ip-check" type="xs:boolean" />
</xs:complexType>
</xs:element>
<xs:element minOccurs="0" name="passive">
<xs:complexType>
- <xs:attribute name="address"/>
- <xs:attribute name="external-address"/>
- <xs:attribute name="ports"/>
+ <xs:attribute name="address" />
+ <xs:attribute name="external-address" />
+ <xs:attribute name="ports" />
</xs:complexType>
</xs:element>
</xs:sequence>
- <xs:attribute name="idle-timeout" type="xs:int"/>
+ <xs:attribute name="idle-timeout" type="xs:int" />
</xs:complexType>
-
</xs:element>
- <xs:element minOccurs="0" name="blacklist" type="xs:string"/>
+ <xs:element minOccurs="0" name="blacklist" type="xs:string" />
</xs:sequence>
- <xs:attribute name="name" use="required" type="xs:string"/>
- <xs:attribute name="local-address"/>
- <xs:attribute name="port" type="xs:int"/>
- <xs:attribute name="idle-timeout" type="xs:int"/>
- <xs:attribute name="implicit-ssl" type="xs:boolean"/>
+ <xs:attribute name="name" use="required" type="xs:string" />
+ <xs:attribute name="local-address" />
+ <xs:attribute name="port" type="xs:int" />
+ <xs:attribute name="idle-timeout" type="xs:int" />
+ <xs:attribute name="implicit-ssl" type="xs:boolean" />
</xs:complexType>
</xs:element>
<!-- Extension element used for defining a custom listener -->
- <xs:element name="listener" type="spring-bean-or-ref-with-name"/>
+ <xs:element name="listener" type="spring-bean-or-ref-with-name" />
<!-- Element used to configure Ftplets for used with the server -->
<xs:element name="ftplets">
@@ -155,11 +148,11 @@
<xs:complexType>
<xs:sequence>
<xs:choice maxOccurs="unbounded">
- <xs:element ref="beans:bean"/>
- <xs:element ref="beans:ref"/>
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
</xs:choice>
</xs:sequence>
- <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="name" use="required" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
@@ -169,40 +162,61 @@
<!-- Element used to configure a file based user manager -->
<xs:element name="file-user-manager">
<xs:complexType>
- <xs:attribute name="file" use="required" type="xs:string"/>
- <xs:attribute name="encrypt-passwords" type="xs:boolean"/>
+ <xs:attribute name="file" use="required" type="xs:string" />
+ <xs:attribute name="encrypt-passwords">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="clear"></xs:enumeration>
+ <!-- Deprecated, use "clear" -->
+ <xs:enumeration value="false"></xs:enumeration>
+ <xs:enumeration value="md5"></xs:enumeration>
+ <!-- Deprecated, use "md5" -->
+ <xs:enumeration value="true"></xs:enumeration>
+ <xs:enumeration value="salted"></xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<!-- Element used to configure a database based user manager -->
<xs:element name="db-user-manager">
<xs:complexType>
- <xs:sequence>
- <xs:element name="data-source" type="spring-bean-or-ref"/>
- <xs:element name="insert-user" type="xs:string"/>
- <xs:element name="update-user" type="xs:string"/>
- <xs:element name="delete-user" type="xs:string"/>
- <xs:element name="select-user" type="xs:string"/>
- <xs:element name="select-all-users" type="xs:string"/>
- <xs:element name="is-admin" type="xs:string"/>
- <xs:element name="authenticate" type="xs:string"/>
+ <xs:sequence>
+ <xs:element name="data-source" type="spring-bean-or-ref" />
+ <xs:element name="insert-user" type="xs:string" />
+ <xs:element name="update-user" type="xs:string" />
+ <xs:element name="delete-user" type="xs:string" />
+ <xs:element name="select-user" type="xs:string" />
+ <xs:element name="select-all-users" type="xs:string" />
+ <xs:element name="is-admin" type="xs:string" />
+ <xs:element name="authenticate" type="xs:string" />
</xs:sequence>
+ <xs:attribute name="encrypt-passwords">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="clear"></xs:enumeration>
+ <xs:enumeration value="md5"></xs:enumeration>
+ <xs:enumeration value="salted"></xs:enumeration>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
</xs:complexType>
</xs:element>
<!-- Extension element used for defining a custom user manager -->
- <xs:element name="user-manager" type="spring-bean-or-ref"/>
+ <xs:element name="user-manager" type="spring-bean-or-ref" />
<!-- Element used to configure the default file system -->
<xs:element name="native-filesystem">
<xs:complexType>
- <xs:attribute name="case-insensitive" type="xs:boolean"/>
- <xs:attribute name="create-home" type="xs:boolean"/>
+ <xs:attribute name="case-insensitive" type="xs:boolean" />
+ <xs:attribute name="create-home" type="xs:boolean" />
</xs:complexType>
</xs:element>
<!-- Extension element used for defining a custom file system -->
- <xs:element name="filesystem" type="spring-bean-or-ref"/>
+ <xs:element name="filesystem" type="spring-bean-or-ref" />
<!-- Element used to provide custom command implementations -->
<xs:element name="commands">
@@ -212,32 +226,31 @@
<xs:complexType>
<xs:sequence>
<xs:choice maxOccurs="unbounded">
- <xs:element ref="beans:bean"/>
- <xs:element ref="beans:ref"/>
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
</xs:choice>
</xs:sequence>
- <xs:attribute name="name" use="required"/>
+ <xs:attribute name="name" use="required" />
</xs:complexType>
-
</xs:element>
</xs:sequence>
- <xs:attribute name="use-default" type="xs:boolean"/>
+ <xs:attribute name="use-default" type="xs:boolean" />
</xs:complexType>
</xs:element>
<!-- Element used to configure and localize messages -->
<xs:element name="messages">
<xs:complexType>
- <xs:attribute name="languages"/>
- <xs:attribute name="directory"/>
+ <xs:attribute name="languages" />
+ <xs:attribute name="directory" />
</xs:complexType>
</xs:element>
<!-- Reusable type used for extension elements -->
<xs:complexType name="spring-bean-or-ref">
<xs:choice>
- <xs:element ref="beans:bean"/>
- <xs:element ref="beans:ref"/>
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
</xs:choice>
</xs:complexType>
@@ -245,12 +258,10 @@
<xs:complexType name="spring-bean-or-ref-with-name">
<xs:sequence>
<xs:choice>
- <xs:element ref="beans:bean"/>
- <xs:element ref="beans:ref"/>
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
</xs:choice>
-
</xs:sequence>
- <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="name" use="required" type="xs:string" />
</xs:complexType>
-
-</xs:schema>
+</xs:schema>
\ No newline at end of file
Modified: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/ClientTestTemplate.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/ClientTestTemplate.java?rev=689495&r1=689494&r2=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/ClientTestTemplate.java (original)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/ClientTestTemplate.java Wed Aug 27 07:58:52 2008
@@ -32,6 +32,7 @@
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.listener.nio.NioListener;
import org.apache.ftpserver.test.TestUtil;
+import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;
import org.apache.ftpserver.usermanager.PropertiesUserManager;
import org.apache.ftpserver.util.IoUtils;
import org.slf4j.Logger;
@@ -87,8 +88,8 @@
PropertiesUserManager userManager = new PropertiesUserManager();
userManager.setAdminName("admin");
- userManager.setEncryptPasswords(false);
- userManager.setPropFile(USERS_FILE);
+ userManager.setPasswordEncryptor(new ClearTextPasswordEncryptor());
+ userManager.setFile(USERS_FILE);
userManager.configure();
context.setUserManager(userManager);
Copied: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/DbUserManagerConfigTest.java (from r686637, mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/XmlDbUserManagerConfigTest.java)
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/DbUserManagerConfigTest.java?p2=mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/DbUserManagerConfigTest.java&p1=mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/XmlDbUserManagerConfigTest.java&r1=686637&r2=689495&rev=689495&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/XmlDbUserManagerConfigTest.java (original)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/DbUserManagerConfigTest.java Wed Aug 27 07:58:52 2008
@@ -19,13 +19,10 @@
package org.apache.ftpserver.config.spring;
-import junit.framework.TestCase;
-
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.usermanager.DbUserManager;
+import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
import org.hsqldb.jdbc.jdbcDataSource;
-import org.springframework.beans.factory.xml.XmlBeanFactory;
-import org.springframework.core.io.FileSystemResource;
/**
*
@@ -33,18 +30,29 @@
* @version $Rev$, $Date$
*
*/
-public class XmlDbUserManagerConfigTest extends TestCase {
+public class DbUserManagerConfigTest extends SpringConfigTestTemplate {
public void test() throws Throwable {
- XmlBeanFactory factory = new XmlBeanFactory(
- new FileSystemResource(
- "src/test/resources/spring-config/config-spring-db-user-manager.xml"));
-
- FtpServer server = (FtpServer) factory.getBean("server");
+ FtpServer server = createServer("<db-user-manager encrypt-passwords=\"salted\">"
+ + "<data-source>"
+ + " <beans:bean class=\"org.hsqldb.jdbc.jdbcDataSource\">"
+ + " <beans:property name=\"database\" value=\"jdbc:hsqldb:mem:foo\" />"
+ + " <beans:property name=\"user\" value=\"sa\" />"
+ + " <beans:property name=\"password\" value=\"\" />"
+ + " </beans:bean>" + "</data-source>"
+ + "<insert-user>INSERT USER</insert-user>"
+ + "<update-user>UPDATE USER</update-user>"
+ + "<delete-user>DELETE USER</delete-user>"
+ + "<select-user>SELECT USER</select-user>"
+ + "<select-all-users>SELECT ALL USERS</select-all-users>"
+ + "<is-admin>IS ADMIN</is-admin>"
+ + "<authenticate>AUTHENTICATE</authenticate>"
+ + "</db-user-manager>");
DbUserManager um = (DbUserManager) server.getServerContext()
.getUserManager();
assertTrue(um.getDataSource() instanceof jdbcDataSource);
+ assertTrue(um.getPasswordEncryptor() instanceof SaltedPasswordEncryptor);
assertEquals("INSERT USER", um.getSqlUserInsert());
assertEquals("UPDATE USER", um.getSqlUserUpdate());
Propchange: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/DbUserManagerConfigTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/FileUserManagerConfigTest.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/FileUserManagerConfigTest.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/FileUserManagerConfigTest.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/FileUserManagerConfigTest.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,77 @@
+/*
+ * 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.ftpserver.config.spring;
+
+import org.apache.ftpserver.FtpServer;
+import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;
+import org.apache.ftpserver.usermanager.Md5PasswordEncryptor;
+import org.apache.ftpserver.usermanager.PropertiesUserManager;
+import org.apache.ftpserver.usermanager.SaltedPasswordEncryptor;
+
+/**
+*
+* @author The Apache MINA Project (dev@mina.apache.org)
+* @version $Rev$, $Date$
+*
+*/
+public class FileUserManagerConfigTest extends SpringConfigTestTemplate {
+
+ private PropertiesUserManager createPropertiesUserManager(String config) {
+ FtpServer server = createServer(config);
+
+ return (PropertiesUserManager) server.getUserManager();
+ }
+
+ public void testFile() throws Throwable {
+ PropertiesUserManager um = createPropertiesUserManager("<file-user-manager file=\"/tmp/foo.users\" />");
+ assertEquals("/tmp/foo.users", um.getFile().getAbsolutePath());
+ }
+
+ public void testMd5PasswordEncryptor() throws Throwable {
+ PropertiesUserManager um = createPropertiesUserManager("<file-user-manager file=\"foo\" encrypt-passwords=\"md5\" />");
+
+ assertTrue(um.getPasswordEncryptor() instanceof Md5PasswordEncryptor);
+ }
+
+ public void testTruePasswordEncryptor() throws Throwable {
+ PropertiesUserManager um = createPropertiesUserManager("<file-user-manager file=\"foo\" encrypt-passwords=\"true\" />");
+
+ assertTrue(um.getPasswordEncryptor() instanceof Md5PasswordEncryptor);
+ }
+
+ public void testNonePasswordEncryptor() throws Throwable {
+ PropertiesUserManager um = createPropertiesUserManager("<file-user-manager file=\"foo\" encrypt-passwords=\"clear\" />");
+
+ assertTrue(um.getPasswordEncryptor() instanceof ClearTextPasswordEncryptor);
+ }
+
+ public void testSaltedPasswordEncryptor() throws Throwable {
+ PropertiesUserManager um = createPropertiesUserManager("<file-user-manager file=\"foo\" encrypt-passwords=\"salted\" />");
+
+ assertTrue(um.getPasswordEncryptor() instanceof SaltedPasswordEncryptor);
+ }
+
+ public void testFalsePasswordEncryptor() throws Throwable {
+ PropertiesUserManager um = createPropertiesUserManager("<file-user-manager file=\"foo\" encrypt-passwords=\"false\" />");
+
+ assertTrue(um.getPasswordEncryptor() instanceof ClearTextPasswordEncryptor);
+ }
+
+}
Propchange: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/FileUserManagerConfigTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTestTemplate.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTestTemplate.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTestTemplate.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTestTemplate.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,53 @@
+/*
+ * 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.ftpserver.config.spring;
+
+import junit.framework.TestCase;
+
+import org.apache.ftpserver.FtpServer;
+import org.springframework.beans.factory.xml.XmlBeanFactory;
+import org.springframework.core.io.ByteArrayResource;
+
+/**
+*
+* @author The Apache MINA Project (dev@mina.apache.org)
+* @version $Rev$, $Date$
+*
+*/
+public abstract class SpringConfigTestTemplate extends TestCase {
+
+ protected FtpServer createServer(String config) {
+ String completeConfig = "<server id=\"server\" xmlns=\"http://mina.apache.org/ftpserver/spring/v1\" "
+ + "xmlns:beans=\"http://www.springframework.org/schema/beans\" "
+ + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ + "xsi:schemaLocation=\" "
+ + "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd "
+ + "http://mina.apache.org/ftpserver/spring/v1 http://mina.apache.org/ftpserver/ftpserver-1.0.xsd "
+ + "\">"
+ + config
+ + "</server>";
+
+ XmlBeanFactory factory = new XmlBeanFactory(
+ new ByteArrayResource(completeConfig.getBytes()));
+
+ return (FtpServer) factory.getBean("server");
+
+ }
+}
Propchange: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTestTemplate.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextDbUserManagerTest.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextDbUserManagerTest.java?rev=689495&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextDbUserManagerTest.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextDbUserManagerTest.java Wed Aug 27 07:58:52 2008
@@ -0,0 +1,53 @@
+/*
+ * 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.ftpserver.usermanager;
+
+import java.io.File;
+import java.io.FileReader;
+import java.sql.Connection;
+import java.sql.Statement;
+
+import org.apache.ftpserver.ftplet.FtpException;
+import org.apache.ftpserver.ftplet.UserManager;
+import org.apache.ftpserver.test.TestUtil;
+import org.apache.ftpserver.util.IoUtils;
+import org.hsqldb.jdbc.jdbcDataSource;
+
+/**
+*
+* @author The Apache MINA Project (dev@mina.apache.org)
+* @version $Rev$, $Date$
+*
+*/
+public class ClearTextDbUserManagerTest extends DbUserManagerTest {
+
+ protected File getInitSqlScript() {
+ return new File(TestUtil.getBaseDir(),
+ "src/test/resources/dbusermanagertest-cleartext-hsql.sql");
+ }
+
+
+ protected UserManager createUserManager() throws FtpException {
+ DbUserManager manager = (DbUserManager) super.createUserManager();
+ manager.setPasswordEncryptor(new ClearTextPasswordEncryptor());
+ return manager;
+
+ }
+}
Propchange: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/usermanager/ClearTextDbUserManagerTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain