@@ -108,6 +108,19 @@ private static RaiseException newSSLError(Ruby runtime, String message) {
108
108
return SSL .newSSLError (runtime , message );
109
109
}
110
110
111
+ private static RaiseException newSSLErrorFromHandshake (Ruby runtime , SSLHandshakeException exception ) {
112
+ // SSLHandshakeException is always a wrap around another exception that
113
+ // is the actual cause. In some cases the diagnostic message from the original
114
+ // exception is also lost and the handshake exception reads "General SSLEngine problem"
115
+ // Follow the cause chain until we get the real message and use that to ensure
116
+ // we raise an exception that contains the real reason for failure
117
+ Exception cause = exception ;
118
+ while (cause .getCause () != null && (cause instanceof SSLHandshakeException )) {
119
+ cause = (Exception ) cause .getCause ();
120
+ }
121
+ return SSL .newSSLError (runtime , cause );
122
+ }
123
+
111
124
private SSLContext sslContext ;
112
125
private SSLEngine engine ;
113
126
private RubyIO io ;
@@ -203,11 +216,7 @@ private IRubyObject connectCommon(final ThreadContext context, boolean blocking)
203
216
// unlike server side, client should close outbound channel even if
204
217
// we have remaining data to be sent.
205
218
forceClose ();
206
- Exception cause = e ;
207
- while (cause .getCause () != null && (cause instanceof SSLHandshakeException )) {
208
- cause = (Exception ) cause .getCause ();
209
- }
210
- throw newSSLError (runtime , cause );
219
+ throw newSSLErrorFromHandshake (runtime , e );
211
220
}
212
221
catch (NoSuchAlgorithmException e ) {
213
222
forceClose ();
@@ -267,7 +276,7 @@ public SSLSocket acceptCommon(final ThreadContext context, boolean blocking) {
267
276
doHandshake (blocking );
268
277
}
269
278
catch (SSLHandshakeException e ) {
270
- throw newSSLError (runtime , e );
279
+ throw newSSLErrorFromHandshake (runtime , e );
271
280
}
272
281
catch (NoSuchAlgorithmException e ) {
273
282
throw newSSLError (runtime , e );
0 commit comments