Skip to content

Commit 8c0c177

Browse files
committed
Map all SSL failures to network error and await server response on control connection. Fix #17946.
1 parent e2a9fec commit 8c0c177

7 files changed

Lines changed: 24 additions & 19 deletions

File tree

core/src/main/java/ch/cyberduck/core/exception/SSLNegotiateException.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@
1515
* GNU General Public License for more details.
1616
*/
1717

18-
public class SSLNegotiateException extends InteroperabilityException {
19-
public SSLNegotiateException(final String detail) {
20-
super(detail);
21-
}
22-
18+
public class SSLNegotiateException extends ConnectionRefusedException {
2319
public SSLNegotiateException(final String detail, final Throwable cause) {
2420
super(detail, cause);
2521
}

core/src/main/java/ch/cyberduck/core/ssl/SSLExceptionMappingService.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import ch.cyberduck.core.DefaultSocketExceptionMappingService;
2323
import ch.cyberduck.core.exception.BackgroundException;
2424
import ch.cyberduck.core.exception.ConnectionCanceledException;
25-
import ch.cyberduck.core.exception.InteroperabilityException;
25+
import ch.cyberduck.core.exception.ConnectionRefusedException;
2626
import ch.cyberduck.core.exception.SSLNegotiateException;
2727

2828
import org.apache.commons.lang3.StringUtils;
@@ -98,10 +98,10 @@ public BackgroundException map(final SSLException failure) {
9898
}
9999
if(ExceptionUtils.getRootCause(failure) instanceof GeneralSecurityException) {
100100
this.append(buffer, ExceptionUtils.getRootCause(failure).getMessage());
101-
return new InteroperabilityException(buffer.toString(), failure);
101+
return new ConnectionRefusedException(buffer.toString(), failure);
102102
}
103103
this.append(buffer, message);
104-
return new InteroperabilityException(buffer.toString(), failure);
104+
return new ConnectionRefusedException(buffer.toString(), failure);
105105
}
106106

107107
private enum Alert {

core/src/main/java/ch/cyberduck/core/threading/DefaultFailureDiagnostics.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import ch.cyberduck.core.exception.LoginFailureException;
3030
import ch.cyberduck.core.exception.QuotaException;
3131
import ch.cyberduck.core.exception.ResolveFailedException;
32-
import ch.cyberduck.core.exception.SSLNegotiateException;
3332
import ch.cyberduck.core.exception.TransferCanceledException;
3433
import ch.cyberduck.core.exception.UnsupportedException;
3534
import ch.cyberduck.core.io.IOResumeException;
@@ -78,9 +77,6 @@ public Type determine(final BackgroundException failure) {
7877
if(cause instanceof ConnectionRefusedException) {
7978
return Type.network;
8079
}
81-
if(cause instanceof SSLNegotiateException) {
82-
return Type.application;
83-
}
8480
if(cause instanceof SSLHandshakeException) {
8581
return Type.application;
8682
}

core/src/test/java/ch/cyberduck/core/ssl/SSLExceptionMappingServiceTest.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,34 @@
1919
*/
2020

2121
import ch.cyberduck.core.exception.BackgroundException;
22+
import ch.cyberduck.core.exception.ConnectionRefusedException;
23+
import ch.cyberduck.core.exception.SSLNegotiateException;
2224

2325
import org.junit.Test;
2426

2527
import javax.net.ssl.SSLException;
28+
import javax.net.ssl.SSLHandshakeException;
2629
import java.net.SocketException;
2730

2831
import static org.junit.Assert.assertEquals;
32+
import static org.junit.Assert.assertSame;
2933

3034
public class SSLExceptionMappingServiceTest {
3135

3236
@Test
33-
public void testMap() {
37+
public void testMapSocketException() {
3438
final BackgroundException f = new SSLExceptionMappingService().map(new SSLException(
3539
"Connection has been shutdown: javax.net.ssl.SSLException: java.net.SocketException: Broken pipe",
3640
new SSLException("javax.net.ssl.SSLException: java.net.SocketException: Broken pipe",
3741
new SocketException("Broken pipe"))));
42+
assertSame(ConnectionRefusedException.class, f.getClass());
3843
assertEquals("Connection failed", f.getMessage());
3944
assertEquals("Broken pipe. The connection attempt was rejected. The server may be down, or your network may not be properly configured.", f.getDetail());
4045
}
46+
47+
@Test
48+
public void testMapSSLFailure() {
49+
final BackgroundException f = new SSLExceptionMappingService().map(new SSLHandshakeException("r"));
50+
assertSame(SSLNegotiateException.class, f.getClass());
51+
}
4152
}

ftp/src/main/java/ch/cyberduck/core/ftp/DataConnectionActionExecutor.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import ch.cyberduck.core.exception.AccessDeniedException;
2121
import ch.cyberduck.core.exception.BackgroundException;
22+
import ch.cyberduck.core.exception.ConnectionRefusedException;
2223
import ch.cyberduck.core.exception.ConnectionTimeoutException;
2324
import ch.cyberduck.core.exception.InteroperabilityException;
2425
import ch.cyberduck.core.exception.NotfoundException;
@@ -55,9 +56,9 @@ public <T> T open(final DataConnectionAction<T> action) throws IOException, Back
5556
}
5657
return action.execute();
5758
}
58-
catch(ConnectionTimeoutException failure) {
59-
log.warn("Timeout opening data socket {}", failure.getMessage());
60-
// Expect 421 response
59+
catch(ConnectionRefusedException | ConnectionTimeoutException failure) {
60+
log.warn("I/O error opening data socket {}", failure.getMessage());
61+
// Drain any pending reply on the control channel to resynchronize after failed data connection
6162
session.getClient().completePendingCommand();
6263
throw failure;
6364
}

ftp/src/test/java/ch/cyberduck/core/ftp/DataConnectionActionExecutorTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
import ch.cyberduck.core.exception.BackgroundException;
21+
import ch.cyberduck.core.exception.InteroperabilityException;
2122
import ch.cyberduck.test.IntegrationTest;
2223

2324
import org.junit.Test;
@@ -29,14 +30,14 @@
2930
public class DataConnectionActionExecutorTest extends AbstractFTPTest {
3031

3132
@Test
32-
public void testFallbackOpenConnection500Error() throws Exception {
33+
public void testServerError() throws Exception {
3334
final DataConnectionAction<Void> action = new DataConnectionAction<Void>() {
3435
@Override
3536
public Void execute() throws BackgroundException {
3637
throw new FTPExceptionMappingService().map(new FTPException(500, "m"));
3738
}
3839
};
3940
final DataConnectionActionExecutor f = new DataConnectionActionExecutor(session);
40-
assertThrows(Exception.class, () -> f.open(action));
41+
assertThrows(InteroperabilityException.class, () -> f.open(action));
4142
}
4243
}

s3/src/test/java/ch/cyberduck/core/s3/S3ExceptionMappingServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public void testWrapped() {
126126

127127
@Test
128128
public void testAlgorithmFailure() {
129-
assertEquals("EC AlgorithmParameters not available. Please contact your web hosting service provider for assistance.",
129+
assertEquals("EC AlgorithmParameters not available. The connection attempt was rejected. The server may be down, or your network may not be properly configured.",
130130
new S3ExceptionMappingService().map(new S3ServiceException(
131131
new SSLException(
132132
new RuntimeException(

0 commit comments

Comments
 (0)