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 2009/05/30 23:39:06 UTC

svn commit: r780332 - in /mina/ftpserver/trunk/core/src: main/java/org/apache/ftpserver/impl/DefaultFtpHandler.java test/java/org/apache/ftpserver/clienttests/DecoderTest.java

Author: ngn
Date: Sat May 30 21:39:05 2009
New Revision: 780332

URL: http://svn.apache.org/viewvc?rev=780332&view=rev
Log:
Return an error reply rather than close the session if we get a decoding problem (FTPSERVER-309)

Added:
    mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/DecoderTest.java
Modified:
    mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpHandler.java

Modified: mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpHandler.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpHandler.java?rev=780332&r1=780331&r2=780332&view=diff
==============================================================================
--- mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpHandler.java (original)
+++ mina/ftpserver/trunk/core/src/main/java/org/apache/ftpserver/impl/DefaultFtpHandler.java Sat May 30 21:39:05 2009
@@ -20,11 +20,13 @@
 package org.apache.ftpserver.impl;
 
 import java.io.IOException;
+import java.nio.charset.MalformedInputException;
 
 import org.apache.ftpserver.command.Command;
 import org.apache.ftpserver.command.CommandFactory;
 import org.apache.ftpserver.ftplet.DataConnection;
 import org.apache.ftpserver.ftplet.DataConnectionFactory;
+import org.apache.ftpserver.ftplet.DefaultFtpReply;
 import org.apache.ftpserver.ftplet.FileSystemView;
 import org.apache.ftpserver.ftplet.FtpReply;
 import org.apache.ftpserver.ftplet.FtpRequest;
@@ -33,6 +35,7 @@
 import org.apache.ftpserver.listener.Listener;
 import org.apache.mina.core.session.IdleStatus;
 import org.apache.mina.core.write.WriteToClosedSessionException;
+import org.apache.mina.filter.codec.ProtocolDecoderException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -135,18 +138,29 @@
 
     public void exceptionCaught(final FtpIoSession session,
             final Throwable cause) throws Exception {
-        if (cause instanceof WriteToClosedSessionException) {
+        
+        if(cause instanceof ProtocolDecoderException &&
+                cause.getCause() instanceof MalformedInputException) {
+            // client probably sent something which is not UTF-8 and we failed to
+            // decode it
+            
+            LOG.warn(
+                    "Client sent command that could not be decoded: {}",
+                    ((ProtocolDecoderException)cause).getHexdump());
+            session.write(new DefaultFtpReply(FtpReply.REPLY_501_SYNTAX_ERROR_IN_PARAMETERS_OR_ARGUMENTS, "Invalid character in command"));
+        } else if (cause instanceof WriteToClosedSessionException) {
             WriteToClosedSessionException writeToClosedSessionException = 
                 (WriteToClosedSessionException) cause;
             LOG.warn(
                             "Client closed connection before all replies could be sent, last reply was {}",
                             writeToClosedSessionException.getRequest());
-
+            session.close(false).awaitUninterruptibly(10000);
         } else {
             LOG.error("Exception caught, closing session", cause);
+            session.close(false).awaitUninterruptibly(10000);
         }
 
-        session.close(false).awaitUninterruptibly(10000);
+
     }
 
     private boolean isCommandOkWithoutAuthentication(String command) {

Added: mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/DecoderTest.java
URL: http://svn.apache.org/viewvc/mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/DecoderTest.java?rev=780332&view=auto
==============================================================================
--- mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/DecoderTest.java (added)
+++ mina/ftpserver/trunk/core/src/test/java/org/apache/ftpserver/clienttests/DecoderTest.java Sat May 30 21:39:05 2009
@@ -0,0 +1,82 @@
+/*
+ * 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.clienttests;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.MalformedInputException;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.net.ftp.FTPClient;
+
+
+/**
+*
+* @author The Apache MINA Project (dev@mina.apache.org)*
+*/
+public class DecoderTest extends ClientTestTemplate {
+    private String dump = "4C 49 53 54 20 61 62 63 64 AE 2E 0D 0A".replace(" ", "");
+    
+    byte[] b;
+
+    public DecoderTest() throws DecoderException {
+        b = Hex.decodeHex(dump.toCharArray());
+    }
+    
+    public void testDecodeError() throws CharacterCodingException {
+        CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+        ByteBuffer buffer = ByteBuffer.wrap(b);
+        
+        try {
+            decoder.decode(buffer);
+            fail("Must throw MalformedInputException");
+        } catch (MalformedInputException e) {
+            // OK
+        }
+    }
+    
+    private static class MyFTPClient extends FTPClient {
+        public void sendRawCommand(byte[] b) throws IOException {
+            OutputStream out =_socket_.getOutputStream();
+            out.write(b);
+        }
+    }
+    
+    protected FTPClient createFTPClient() throws Exception {
+        FTPClient client = new MyFTPClient();
+        client.setDefaultTimeout(10000);
+        return client;
+    }
+
+    public void testInvalidCharacter() throws Exception {
+        client.login(ADMIN_USERNAME, ADMIN_PASSWORD);
+
+        ((MyFTPClient)client).sendRawCommand(b);
+        client.completePendingCommand();
+
+        assertEquals(501, client.getReplyCode());
+    }
+
+}