Implemented JIRA Issue FTPSERVER-323
git-svn-id: https://svn.apache.org/repos/asf/mina/ftpserver/trunk@807631 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core/src/main/java/org/apache/ftpserver/DataConnectionConfiguration.java b/core/src/main/java/org/apache/ftpserver/DataConnectionConfiguration.java
index f689368..136d6f1 100644
--- a/core/src/main/java/org/apache/ftpserver/DataConnectionConfiguration.java
+++ b/core/src/main/java/org/apache/ftpserver/DataConnectionConfiguration.java
@@ -91,6 +91,18 @@
* @return The passive ports string
*/
String getPassivePorts();
+
+ /**
+ * Tells whether or not IP address check is performed when accepting a
+ * passive data connection.
+ *
+ * @return <code>true</code>, if the IP address checking is enabled;
+ * <code>false</code>, otherwise. A value of <code>true</code> means
+ * that site to site transfers are disabled. In other words, a
+ * passive data connection MUST be made from the same IP address
+ * that issued the PASV command.
+ */
+ boolean isPassiveIpCheck();
/**
* Request a passive port. Will block until a port is available
diff --git a/core/src/main/java/org/apache/ftpserver/DataConnectionConfigurationFactory.java b/core/src/main/java/org/apache/ftpserver/DataConnectionConfigurationFactory.java
index 7743ab4..9834bfe 100644
--- a/core/src/main/java/org/apache/ftpserver/DataConnectionConfigurationFactory.java
+++ b/core/src/main/java/org/apache/ftpserver/DataConnectionConfigurationFactory.java
@@ -49,6 +49,7 @@
private String passiveAddress;
private String passiveExternalAddress;
private PassivePorts passivePorts = new PassivePorts(new int[] { 0 }, true);
+ private boolean passiveIpCheck = false;
private boolean implicitSsl;
/**
@@ -62,7 +63,7 @@
ssl, activeEnabled, activeIpCheck,
activeLocalAddress, activeLocalPort,
passiveAddress, passivePorts,
- passiveExternalAddress, implicitSsl);
+ passiveExternalAddress, passiveIpCheck, implicitSsl);
}
/*
* (Non-Javadoc)
@@ -197,6 +198,32 @@
}
/**
+ * Tells whether or not IP address check is performed when accepting a
+ * passive data connection.
+ *
+ * @return <code>true</code>, if the IP address checking is enabled;
+ * <code>false</code>, otherwise. A value of <code>true</code> means
+ * that site to site transfers are disabled. In other words, a
+ * passive data connection MUST be made from the same IP address
+ * that issued the PASV command.
+ */
+ public boolean isPassiveIpCheck() {
+ return passiveIpCheck;
+ }
+
+ /**
+ * Sets whether or not IP check is performed before accepting a passive data
+ * connection.
+ *
+ * @param passiveIpCheck
+ * whether or not IP check is performed before accepting a
+ * passive data connection.
+ */
+ public void setPassiveIpCheck(boolean passiveIpCheck) {
+ this.passiveIpCheck = passiveIpCheck;
+ }
+
+ /**
* Get passive data port. Data port number zero (0) means that any available
* port will be used.
* @return A passive port to use
diff --git a/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java b/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java
index dbe31fb..060d18f 100644
--- a/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java
+++ b/core/src/main/java/org/apache/ftpserver/config/spring/ListenerBeanDefinitionParser.java
@@ -299,6 +299,8 @@
if (ports != null) {
dc.setPassivePorts(ports);
}
+ dc.setPassiveIpCheck(SpringUtil.parseBoolean(passiveElm,
+ "ip-check", false));
}
} else {
// no data conn config element, do we still have SSL config from the
diff --git a/core/src/main/java/org/apache/ftpserver/impl/DefaultDataConnectionConfiguration.java b/core/src/main/java/org/apache/ftpserver/impl/DefaultDataConnectionConfiguration.java
index aa7a748..b55d2ac 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/DefaultDataConnectionConfiguration.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/DefaultDataConnectionConfiguration.java
@@ -45,28 +45,31 @@
private String passiveAddress;
private String passiveExternalAddress;
private PassivePorts passivePorts;
+ private boolean passiveIpCheck;
private final boolean implicitSsl;
/**
- * Internal constructor, do not use directly. Use {@link DataConnectionConfigurationFactory} instead.
- */
- public DefaultDataConnectionConfiguration(int idleTime,
- SslConfiguration ssl, boolean activeEnabled, boolean activeIpCheck,
- String activeLocalAddress, int activeLocalPort,
- String passiveAddress, PassivePorts passivePorts,
- String passiveExternalAddress, boolean implicitSsl) {
- this.idleTime = idleTime;
- this.ssl = ssl;
- this.activeEnabled = activeEnabled;
- this.activeIpCheck = activeIpCheck;
- this.activeLocalAddress = activeLocalAddress;
- this.activeLocalPort = activeLocalPort;
- this.passiveAddress = passiveAddress;
- this.passivePorts = passivePorts;
- this.passiveExternalAddress = passiveExternalAddress;
- this.implicitSsl = implicitSsl;
- }
+ * Internal constructor, do not use directly. Use
+ * {@link DataConnectionConfigurationFactory} instead.
+ */
+ public DefaultDataConnectionConfiguration(int idleTime,
+ SslConfiguration ssl, boolean activeEnabled, boolean activeIpCheck,
+ String activeLocalAddress, int activeLocalPort, String passiveAddress,
+ PassivePorts passivePorts, String passiveExternalAddress,
+ boolean passiveIpCheck, boolean implicitSsl) {
+ this.idleTime = idleTime;
+ this.ssl = ssl;
+ this.activeEnabled = activeEnabled;
+ this.activeIpCheck = activeIpCheck;
+ this.activeLocalAddress = activeLocalAddress;
+ this.activeLocalPort = activeLocalPort;
+ this.passiveAddress = passiveAddress;
+ this.passivePorts = passivePorts;
+ this.passiveExternalAddress = passiveExternalAddress;
+ this.passiveIpCheck = passiveIpCheck;
+ this.implicitSsl = implicitSsl;
+ }
/**
* Get the maximum idle time in seconds.
@@ -115,8 +118,12 @@
*/
public String getPassiveExernalAddress() {
return passiveExternalAddress;
- }
-
+ }
+
+ public boolean isPassiveIpCheck() {
+ return passiveIpCheck;
+ }
+
/**
* Get passive data port. Data port number zero (0) means that any available
* port will be used.
diff --git a/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java b/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java
index fe4ec7c..01558d2 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java
@@ -355,6 +355,22 @@
dataSoc = servSoc.accept();
}
+
+ if (dataConfig.isPassiveIpCheck()) {
+ // Let's make sure we got the connection from the same
+ // client that we are expecting
+ InetAddress remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress();
+ InetAddress dataSocketAddress = dataSoc.getInetAddress();
+ if (!dataSocketAddress.equals(remoteAddress)) {
+ LOG.warn("Passive IP Check failed. Closing data connection from "
+ + dataSocketAddress
+ + " as it does not match the expected address "
+ + remoteAddress);
+ closeDataConnection();
+ return null;
+ }
+ }
+
DataConnectionConfiguration dataCfg = session.getListener()
.getDataConnectionConfiguration();
diff --git a/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd b/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
index 872c777..74fd74d 100644
--- a/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
+++ b/core/src/main/resources/org/apache/ftpserver/config/spring/ftpserver-1.0.xsd
@@ -1,270 +1,271 @@
-<?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">
-
- <!-- 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" />
-
- <!-- The main entry point, used for setting up an entire FTP server -->
- <xs:element name="server">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" name="listeners">
- <xs:complexType>
- <xs:choice minOccurs="1" maxOccurs="unbounded">
- <xs:element ref="nio-listener" />
- <xs:element ref="listener" />
- </xs:choice>
- </xs:complexType>
- </xs:element>
- <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:choice>
- <xs:choice minOccurs="0" maxOccurs="1">
- <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: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:complexType>
- </xs:element>
-
- <!-- Reusable element for defining SSL properties -->
- <xs:element name="ssl">
- <xs:complexType>
- <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: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: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:attribute name="protocol">
- <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>
-
- <!-- Element used to define the default, NIO based listener -->
- <xs:element name="nio-listener">
- <xs:complexType>
- <xs:sequence>
- <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" 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: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:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="idle-timeout" type="xs:int" />
- <xs:attribute name="implicit-ssl" type="xs:boolean" />
- </xs:complexType>
- </xs:element>
- <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:complexType>
- </xs:element>
-
- <!-- Extension element used for defining a custom listener -->
- <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">
- <xs:complexType>
- <xs:choice>
- <xs:element name="ftplet" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:choice>
- <xs:element ref="beans:bean" />
- <xs:element ref="beans:ref" />
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="name" use="required" type="xs:string" />
- </xs:complexType>
- </xs:element>
- <xs:element ref="beans:map" />
- </xs:choice>
- </xs:complexType>
- </xs:element>
-
- <!-- Element used to configure a file based user manager -->
- <xs:element name="file-user-manager">
- <xs:complexType>
- <xs:attribute name="file" type="xs:string" />
- <xs:attribute name="url" 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: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" />
-
- <!-- 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:complexType>
- </xs:element>
-
- <!-- Extension element used for defining a custom file system -->
- <xs:element name="filesystem" type="spring-bean-or-ref" />
-
- <!-- Element used to provide custom command implementations -->
- <xs:element name="commands">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="command" maxOccurs="unbounded">
- <xs:complexType>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="beans:bean" />
- <xs:element ref="beans:ref" />
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="name" use="required" />
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <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: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:choice>
- </xs:complexType>
-
- <!-- Reusable type used for named extension elements -->
- <xs:complexType name="spring-bean-or-ref-with-name">
- <xs:sequence>
- <xs:choice>
- <xs:element ref="beans:bean" />
- <xs:element ref="beans:ref" />
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="name" use="required" type="xs:string" />
- </xs:complexType>
+<?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">
+
+ <!-- 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" />
+
+ <!-- The main entry point, used for setting up an entire FTP server -->
+ <xs:element name="server">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" name="listeners">
+ <xs:complexType>
+ <xs:choice minOccurs="1" maxOccurs="unbounded">
+ <xs:element ref="nio-listener" />
+ <xs:element ref="listener" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+ <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:choice>
+ <xs:choice minOccurs="0" maxOccurs="1">
+ <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: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:complexType>
+ </xs:element>
+
+ <!-- Reusable element for defining SSL properties -->
+ <xs:element name="ssl">
+ <xs:complexType>
+ <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: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: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:attribute name="protocol">
+ <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>
+
+ <!-- Element used to define the default, NIO based listener -->
+ <xs:element name="nio-listener">
+ <xs:complexType>
+ <xs:sequence>
+ <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" 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:complexType>
+ </xs:element>
+ <xs:element minOccurs="0" name="passive">
+ <xs:complexType>
+ <xs:attribute name="address" />
+ <xs:attribute name="external-address" />
+ <xs:attribute name="ip-check" type="xs:boolean" />
+ <xs:attribute name="ports" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="idle-timeout" type="xs:int" />
+ <xs:attribute name="implicit-ssl" type="xs:boolean" />
+ </xs:complexType>
+ </xs:element>
+ <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:complexType>
+ </xs:element>
+
+ <!-- Extension element used for defining a custom listener -->
+ <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">
+ <xs:complexType>
+ <xs:choice>
+ <xs:element name="ftplet" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice>
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element ref="beans:map" />
+ </xs:choice>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- Element used to configure a file based user manager -->
+ <xs:element name="file-user-manager">
+ <xs:complexType>
+ <xs:attribute name="file" type="xs:string" />
+ <xs:attribute name="url" 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: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" />
+
+ <!-- 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:complexType>
+ </xs:element>
+
+ <!-- Extension element used for defining a custom file system -->
+ <xs:element name="filesystem" type="spring-bean-or-ref" />
+
+ <!-- Element used to provide custom command implementations -->
+ <xs:element name="commands">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="command" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:choice maxOccurs="unbounded">
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <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: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:choice>
+ </xs:complexType>
+
+ <!-- Reusable type used for named extension elements -->
+ <xs:complexType name="spring-bean-or-ref-with-name">
+ <xs:sequence>
+ <xs:choice>
+ <xs:element ref="beans:bean" />
+ <xs:element ref="beans:ref" />
+ </xs:choice>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string" />
+ </xs:complexType>
</xs:schema>
\ No newline at end of file
diff --git a/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java b/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java
index 366dc2b..cd02c1b 100644
--- a/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java
+++ b/core/src/test/java/org/apache/ftpserver/config/spring/SpringConfigTest.java
@@ -77,6 +77,8 @@
.getDataConnectionConfiguration().getActiveLocalAddress()) );
assertEquals("123-125", ((NioListener) listener)
.getDataConnectionConfiguration().getPassivePorts());
+ assertEquals(false, ((NioListener) listener)
+ .getDataConnectionConfiguration().isPassiveIpCheck());
List<Subnet> subnets = ((NioListener) listener).getBlockedSubnets();
assertEquals(3, subnets.size());