1 package ch
.cyberduck
.core
.ssl
;
4 * Copyright (c) 2002-2014 David Kocher. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * Bug fixes, suggestions and comments should be sent to:
18 * feedback@cyberduck.io
21 import ch
.cyberduck
.core
.AbstractExceptionMappingService
;
22 import ch
.cyberduck
.core
.exception
.BackgroundException
;
23 import ch
.cyberduck
.core
.exception
.ConnectionCanceledException
;
24 import ch
.cyberduck
.core
.exception
.ConnectionRefusedException
;
25 import ch
.cyberduck
.core
.exception
.InteroperabilityException
;
27 import org
.apache
.commons
.lang3
.StringUtils
;
28 import org
.apache
.commons
.lang3
.exception
.ExceptionUtils
;
29 import org
.apache
.log4j
.Logger
;
31 import javax
.net
.ssl
.SSLException
;
32 import javax
.net
.ssl
.SSLHandshakeException
;
33 import java
.net
.SocketException
;
34 import java
.security
.GeneralSecurityException
;
35 import java
.security
.cert
.CertificateException
;
40 public class SSLExceptionMappingService
extends AbstractExceptionMappingService
<SSLException
> {
41 private static final Logger log
= Logger
.getLogger(SSLExceptionMappingService
.class);
45 unexpected_message(10) {
47 public String
getDescription() {
48 return String
.format("%s. An inappropriate message was received.", super.getDescription());
53 public String
getDescription() {
54 return String
.format("%s. A record is received with an incorrect MAC.", super.getDescription());
57 decryption_failed_RESERVED(21),
59 decompression_failure(30),
60 handshake_failure(40) {
62 public String
getDescription() {
63 return String
.format("%s. Unable to negotiate an acceptable set of security parameters.", super.getDescription());
66 no_certificate_RESERVED(41),
69 public String
getDescription() {
70 return String
.format("%s. The certificate provided could not be verified by the server.", super.getDescription());
73 unsupported_certificate(43) {
75 public String
getDescription() {
76 return String
.format("%s. The certificate type provided is not supported by the server.", super.getDescription());
79 certificate_revoked(44) {
81 public String
getDescription() {
82 return String
.format("%s. The certificate provided has been revoked by its signer.", super.getDescription());
85 certificate_expired(45) {
87 public String
getDescription() {
88 return String
.format("%s. The certificate provided has expired.", super.getDescription());
91 certificate_unknown(46) {
93 public String
getDescription() {
94 return String
.format("%s. The certificate provided was not accepted by the server.", super.getDescription());
97 illegal_parameter(47),
100 public String
getDescription() {
101 return String
.format("%s. A valid certificate chain or partial chain was received, but " +
102 "the certificate was not accepted because the certificate authority certificate could not be located " +
103 "or couldn't be matched with a known, trusted certificate authority.", super.getDescription());
108 public String
getDescription() {
109 return String
.format("%s. A valid certificate was received, but when access control was " +
110 "applied, the server decided not to proceed with negotiation.", super.getDescription());
115 export_restriction_RESERVED(60),
116 protocol_version(70) {
118 public String
getDescription() {
119 return String
.format("%s. The protocol version attempted to negotiate is recognized but not supported.", super.getDescription());
122 insufficient_security(71) {
124 public String
getDescription() {
125 return String
.format("%s. The server requires ciphers more secure than those supported.", super.getDescription());
130 no_renegotiation(100),
131 unsupported_extension(110);
135 private Alert(int code
) {
139 public int getCode() {
143 public String
getDescription() {
144 return StringUtils
.capitalize(StringUtils
.replaceChars(this.name(), '_', ' '));
150 * unexpected_message(10),
151 * bad_record_mac(20),
152 * decryption_failed_RESERVED(21),
153 * record_overflow(22),
154 * decompression_failure(30),
155 * handshake_failure(40),
156 * no_certificate_RESERVED(41),
157 * bad_certificate(42),
158 * unsupported_certificate(43),
159 * certificate_revoked(44),
160 * certificate_expired(45),
161 * certificate_unknown(46),
162 * illegal_parameter(47),
167 * export_restriction_RESERVED(60),
168 * protocol_version(70),
169 * insufficient_security(71),
170 * internal_error(80),
172 * no_renegotiation(100),
173 * unsupported_extension(110),
176 public BackgroundException
map(final SSLException failure
) {
177 final StringBuilder buffer
= new StringBuilder();
178 if(ExceptionUtils
.getRootCause(failure
) instanceof SocketException
) {
179 // Map Connection has been shutdown: javax.net.ssl.SSLException: java.net.SocketException: Broken pipe
180 this.append(buffer
, ExceptionUtils
.getRootCause(failure
).getMessage());
181 return new ConnectionRefusedException(buffer
.toString(), failure
);
183 if(failure
instanceof SSLHandshakeException
) {
184 if(ExceptionUtils
.getRootCause(failure
) instanceof CertificateException
) {
185 log
.warn(String
.format("Ignore certificate failure %s and drop connection", failure
.getMessage()));
186 // Server certificate not accepted
187 return new ConnectionCanceledException(failure
);
190 if(ExceptionUtils
.getRootCause(failure
) instanceof GeneralSecurityException
) {
191 this.append(buffer
, ExceptionUtils
.getRootCause(failure
).getMessage());
192 return new InteroperabilityException(buffer
.toString(), failure
);
194 final String message
= failure
.getMessage();
195 for(Alert alert
: Alert
.values()) {
196 if(StringUtils
.contains(message
, alert
.name())) {
197 this.append(buffer
, alert
.getDescription());
201 if(buffer
.length() == 0) {
202 this.append(buffer
, message
);
204 return new InteroperabilityException(buffer
.toString(), failure
);