aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java85
-rwxr-xr-xojluni/src/main/java/sun/net/ftp/impl/FtpClient.java19
2 files changed, 100 insertions, 4 deletions
diff --git a/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java b/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
new file mode 100644
index 00000000000..806ae73fb0f
--- /dev/null
+++ b/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed 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 libcore.java.net;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import sun.net.ftp.FtpLoginException;
+
+/**
+ * Tests URLConnections for ftp:// URLs.
+ */
+public class FtpURLConnectionTest extends TestCase {
+
+ private static final String FILE_PATH = "test/file/for/FtpURLConnectionTest.txt";
+ private static final String SERVER_HOSTNAME = "localhost";
+
+ // http://b/35784677
+ public void testCRLFInUserinfo() throws Exception {
+ List<String> encodedUserInfos = Arrays.asList(
+ // '\r\n' in the username with password
+ "user%0D%0Acommand:password",
+ // '\r\n' in the password
+ "user:password%0D%0Acommand",
+ // just '\n' in the password
+ "user:password%0Acommand",
+ // just '\n' in the username
+ "user%0Acommand:password"
+ );
+ for (String encodedUserInfo : encodedUserInfos) {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ ServerSocket mockFtpServerSocket = new ServerSocket(0);
+ Future<Void> future = executor.submit(new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ Socket clientSocket = mockFtpServerSocket.accept();
+ clientSocket.getOutputStream().write("220 o/".getBytes());
+ clientSocket.close();
+ return null;
+ }
+ });
+ executor.shutdown();
+
+ String urlString = String.format(Locale.US, "ftp://%s@%s:%s/%s",
+ encodedUserInfo, SERVER_HOSTNAME, mockFtpServerSocket.getLocalPort(), FILE_PATH);
+ try {
+ new URL(urlString).openConnection().connect();
+ fail("Connection shouldn't have succeeded: " + urlString);
+ } catch (FtpLoginException expected) {
+ // The original message "Illegal carriage return" gets lost
+ // where FtpURLConnection.connect() translates the
+ // original FtpProtocolException into FtpLoginException.
+ assertEquals("Invalid username/password", expected.getMessage());
+ }
+
+ // Cleanup
+ future.get();
+ mockFtpServerSocket.close();
+ }
+ }
+}
diff --git a/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java b/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java
index 61c4a95ea41..fea94218b7a 100755
--- a/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java
+++ b/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -518,7 +518,8 @@ public class FtpClient extends sun.net.ftp.FtpClient {
* @return <code>true</code> if the command was successful
* @throws IOException
*/
- private boolean issueCommand(String cmd) throws IOException {
+ private boolean issueCommand(String cmd) throws IOException,
+ sun.net.ftp.FtpProtocolException {
if (!isConnected()) {
throw new IllegalStateException("Not connected");
}
@@ -529,6 +530,12 @@ public class FtpClient extends sun.net.ftp.FtpClient {
// ignore...
}
}
+ if (cmd.indexOf('\n') != -1) {
+ sun.net.ftp.FtpProtocolException ex
+ = new sun.net.ftp.FtpProtocolException("Illegal FTP command");
+ ex.initCause(new IllegalArgumentException("Illegal carriage return"));
+ throw ex;
+ }
sendServer(cmd + "\r\n");
return readReply();
}
@@ -1121,7 +1128,10 @@ public class FtpClient extends sun.net.ftp.FtpClient {
*/
public void close() throws IOException {
if (isConnected()) {
- issueCommand("QUIT");
+ try {
+ issueCommand("QUIT");
+ } catch (FtpProtocolException e) {
+ }
loggedIn = false;
}
disconnect();
@@ -1899,7 +1909,8 @@ public class FtpClient extends sun.net.ftp.FtpClient {
return null;
}
- private boolean sendSecurityData(byte[] buf) throws IOException {
+ private boolean sendSecurityData(byte[] buf) throws IOException,
+ sun.net.ftp.FtpProtocolException {
BASE64Encoder encoder = new BASE64Encoder();
String s = encoder.encode(buf);
return issueCommand("ADAT " + s);