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());