Skip to content

Commit ca9b9b9

Browse files
davidbentargos
authored andcommitted
tls: don't treat fatal TLS alerts as EOF
SSL_RECEIVED_SHUTDOWN means not just close_notify or fatal alert. From what I can tell, this was just a mistake? OnStreamRead's comment suggests eof_ was intended to be for close_notify. This fixes a bug in TLSSocket error reporting that seems to have made it into existing tests. If we receive a fatal alert, EmitRead(UV_EOF) would, via onConnectEnd in _tls_wrap.js, synthesize an ECONNRESET before the alert itself is surfaced. As a result, TLS alerts received during the handshake are misreported by Node. See the tests that had to be updated as part of this. PR-URL: #44563 Reviewed-By: Luigi Pinca <[email protected]>
1 parent d08a574 commit ca9b9b9

7 files changed

+51
-44
lines changed

src/crypto/crypto_tls.cc

+9-14
Original file line numberDiff line numberDiff line change
@@ -728,30 +728,25 @@ void TLSWrap::ClearOut() {
728728
// change OpenSSL's error queue, modify ssl_, or even destroy ssl_
729729
// altogether.
730730
if (read <= 0) {
731-
int err = SSL_get_error(ssl_.get(), read);
732-
unsigned long ssl_err = ERR_peek_error(); // NOLINT(runtime/int)
733-
const std::string error_str = GetBIOError();
734-
735-
int flags = SSL_get_shutdown(ssl_.get());
736-
if (!eof_ && flags & SSL_RECEIVED_SHUTDOWN) {
737-
eof_ = true;
738-
EmitRead(UV_EOF);
739-
}
740-
741731
HandleScope handle_scope(env()->isolate());
742732
Local<Value> error;
733+
int err = SSL_get_error(ssl_.get(), read);
743734
switch (err) {
744735
case SSL_ERROR_ZERO_RETURN:
745-
// Ignore ZERO_RETURN after EOF, it is basically not an error.
746-
if (eof_) return;
747-
error = env()->zero_return_string();
748-
break;
736+
if (!eof_) {
737+
eof_ = true;
738+
EmitRead(UV_EOF);
739+
}
740+
return;
749741

750742
case SSL_ERROR_SSL:
751743
case SSL_ERROR_SYSCALL:
752744
{
745+
unsigned long ssl_err = ERR_peek_error(); // NOLINT(runtime/int)
746+
753747
Local<Context> context = env()->isolate()->GetCurrentContext();
754748
if (UNLIKELY(context.IsEmpty())) return;
749+
const std::string error_str = GetBIOError();
755750
Local<String> message = OneByteString(
756751
env()->isolate(), error_str.c_str(), error_str.size());
757752
if (UNLIKELY(message.IsEmpty())) return;

src/env_properties.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,7 @@
321321
V(writable_string, "writable") \
322322
V(write_host_object_string, "_writeHostObject") \
323323
V(write_queue_size_string, "writeQueueSize") \
324-
V(x_forwarded_string, "x-forwarded-for") \
325-
V(zero_return_string, "ZERO_RETURN")
324+
V(x_forwarded_string, "x-forwarded-for")
326325

327326
#define PER_ISOLATE_TEMPLATE_PROPERTIES(V) \
328327
V(async_wrap_ctor_template, v8::FunctionTemplate) \

test/parallel/test-tls-client-auth.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ connect({
7979
}, function(err, pair, cleanup) {
8080
assert.strictEqual(pair.server.err.code,
8181
'ERR_SSL_PEER_DID_NOT_RETURN_A_CERTIFICATE');
82-
assert.strictEqual(pair.client.err.code, 'ECONNRESET');
82+
assert.strictEqual(pair.client.err.code,
83+
'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE');
8384
return cleanup();
8485
});
8586

test/parallel/test-tls-empty-sni-context.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ const server = tls.createServer(options, (c) => {
2626
}, common.mustNotCall());
2727

2828
c.on('error', common.mustCall((err) => {
29-
assert.match(err.message, /Client network socket disconnected/);
29+
assert.strictEqual(err.code, 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE');
3030
}));
3131
}));

test/parallel/test-tls-min-max-version.js

+28-15
Original file line numberDiff line numberDiff line change
@@ -120,23 +120,27 @@ test(U, U, 'TLS_method', U, U, 'TLSv1_2_method', 'TLSv1.2');
120120
test(U, U, 'TLS_method', U, U, 'TLSv1_1_method', 'TLSv1.1');
121121
test(U, U, 'TLS_method', U, U, 'TLSv1_method', 'TLSv1');
122122

123+
// OpenSSL 1.1.1 and 3.0 use a different error code and alert (sent to the
124+
// client) when no protocols are enabled on the server.
125+
const NO_PROTOCOLS_AVAILABLE_SERVER = common.hasOpenSSL3 ?
126+
'ERR_SSL_NO_PROTOCOLS_AVAILABLE' : 'ERR_SSL_INTERNAL_ERROR';
127+
const NO_PROTOCOLS_AVAILABLE_SERVER_ALERT = common.hasOpenSSL3 ?
128+
'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION' : 'ERR_SSL_TLSV1_ALERT_INTERNAL_ERROR';
129+
123130
// SSLv23 also means "any supported protocol" greater than the default
124131
// minimum (which is configurable via command line).
125132
if (DEFAULT_MIN_VERSION === 'TLSv1.3') {
126133
test(U, U, 'TLSv1_2_method', U, U, 'SSLv23_method',
127-
U, 'ECONNRESET', common.hasOpenSSL3 ?
128-
'ERR_SSL_NO_PROTOCOLS_AVAILABLE' : 'ERR_SSL_INTERNAL_ERROR');
134+
U, NO_PROTOCOLS_AVAILABLE_SERVER_ALERT, NO_PROTOCOLS_AVAILABLE_SERVER);
129135
} else {
130136
test(U, U, 'TLSv1_2_method', U, U, 'SSLv23_method', 'TLSv1.2');
131137
}
132138

133139
if (DEFAULT_MIN_VERSION === 'TLSv1.3') {
134140
test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method',
135-
U, 'ECONNRESET', common.hasOpenSSL3 ?
136-
'ERR_SSL_NO_PROTOCOLS_AVAILABLE' : 'ERR_SSL_INTERNAL_ERROR');
141+
U, NO_PROTOCOLS_AVAILABLE_SERVER_ALERT, NO_PROTOCOLS_AVAILABLE_SERVER);
137142
test(U, U, 'TLSv1_method', U, U, 'SSLv23_method',
138-
U, 'ECONNRESET', common.hasOpenSSL3 ?
139-
'ERR_SSL_NO_PROTOCOLS_AVAILABLE' : 'ERR_SSL_INTERNAL_ERROR');
143+
U, NO_PROTOCOLS_AVAILABLE_SERVER_ALERT, NO_PROTOCOLS_AVAILABLE_SERVER);
140144
test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method',
141145
U, 'ERR_SSL_NO_PROTOCOLS_AVAILABLE', 'ERR_SSL_UNEXPECTED_MESSAGE');
142146
test(U, U, 'SSLv23_method', U, U, 'TLSv1_method',
@@ -145,9 +149,11 @@ if (DEFAULT_MIN_VERSION === 'TLSv1.3') {
145149

146150
if (DEFAULT_MIN_VERSION === 'TLSv1.2') {
147151
test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method',
148-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
152+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
153+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
149154
test(U, U, 'TLSv1_method', U, U, 'SSLv23_method',
150-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
155+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
156+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
151157
test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method',
152158
U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER');
153159
test(U, U, 'SSLv23_method', U, U, 'TLSv1_method',
@@ -157,7 +163,8 @@ if (DEFAULT_MIN_VERSION === 'TLSv1.2') {
157163
if (DEFAULT_MIN_VERSION === 'TLSv1.1') {
158164
test(U, U, 'TLSv1_1_method', U, U, 'SSLv23_method', 'TLSv1.1');
159165
test(U, U, 'TLSv1_method', U, U, 'SSLv23_method',
160-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
166+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
167+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
161168
test(U, U, 'SSLv23_method', U, U, 'TLSv1_1_method', 'TLSv1.1');
162169
test(U, U, 'SSLv23_method', U, U, 'TLSv1_method',
163170
U, 'ERR_SSL_UNSUPPORTED_PROTOCOL', 'ERR_SSL_WRONG_VERSION_NUMBER');
@@ -179,9 +186,11 @@ test(U, U, 'TLSv1_method', U, U, 'TLSv1_method', 'TLSv1');
179186
// The default default.
180187
if (DEFAULT_MIN_VERSION === 'TLSv1.2') {
181188
test(U, U, 'TLSv1_1_method', U, U, U,
182-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
189+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
190+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
183191
test(U, U, 'TLSv1_method', U, U, U,
184-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
192+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
193+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
185194

186195
if (DEFAULT_MAX_VERSION === 'TLSv1.2') {
187196
test(U, U, U, U, U, 'TLSv1_1_method',
@@ -191,17 +200,20 @@ if (DEFAULT_MIN_VERSION === 'TLSv1.2') {
191200
} else {
192201
// TLS1.3 client hellos are are not understood by TLS1.1 or below.
193202
test(U, U, U, U, U, 'TLSv1_1_method',
194-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
203+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
204+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
195205
test(U, U, U, U, U, 'TLSv1_method',
196-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
206+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
207+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
197208
}
198209
}
199210

200211
// The default with --tls-v1.1.
201212
if (DEFAULT_MIN_VERSION === 'TLSv1.1') {
202213
test(U, U, 'TLSv1_1_method', U, U, U, 'TLSv1.1');
203214
test(U, U, 'TLSv1_method', U, U, U,
204-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
215+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
216+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
205217
test(U, U, U, U, U, 'TLSv1_1_method', 'TLSv1.1');
206218

207219
if (DEFAULT_MAX_VERSION === 'TLSv1.2') {
@@ -210,7 +222,8 @@ if (DEFAULT_MIN_VERSION === 'TLSv1.1') {
210222
} else {
211223
// TLS1.3 client hellos are are not understood by TLS1.1 or below.
212224
test(U, U, U, U, U, 'TLSv1_method',
213-
U, 'ECONNRESET', 'ERR_SSL_UNSUPPORTED_PROTOCOL');
225+
U, 'ERR_SSL_TLSV1_ALERT_PROTOCOL_VERSION',
226+
'ERR_SSL_UNSUPPORTED_PROTOCOL');
214227
}
215228
}
216229

test/parallel/test-tls-psk-circuit.js

+5-7
Original file line numberDiff line numberDiff line change
@@ -49,24 +49,22 @@ function test(secret, opts, error) {
4949
} else {
5050
const client = tls.connect(options, common.mustNotCall());
5151
client.on('error', common.mustCall((err) => {
52-
assert.strictEqual(err.message, error);
52+
assert.strictEqual(err.code, error);
5353
server.close();
5454
}));
5555
}
5656
}));
5757
}
5858

59-
const DISCONNECT_MESSAGE =
60-
'Client network socket disconnected before ' +
61-
'secure TLS connection was established';
62-
6359
test({ psk: USERS.UserA, identity: 'UserA' });
6460
test({ psk: USERS.UserA, identity: 'UserA' }, { maxVersion: 'TLSv1.2' });
6561
test({ psk: USERS.UserA, identity: 'UserA' }, { minVersion: 'TLSv1.3' });
6662
test({ psk: USERS.UserB, identity: 'UserB' });
6763
test({ psk: USERS.UserB, identity: 'UserB' }, { minVersion: 'TLSv1.3' });
6864
// Unrecognized user should fail handshake
69-
test({ psk: USERS.UserB, identity: 'UserC' }, {}, DISCONNECT_MESSAGE);
65+
test({ psk: USERS.UserB, identity: 'UserC' }, {},
66+
'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE');
7067
// Recognized user but incorrect secret should fail handshake
71-
test({ psk: USERS.UserA, identity: 'UserB' }, {}, DISCONNECT_MESSAGE);
68+
test({ psk: USERS.UserA, identity: 'UserB' }, {},
69+
'ERR_SSL_SSLV3_ALERT_ILLEGAL_PARAMETER');
7270
test({ psk: USERS.UserB, identity: 'UserB' });

test/parallel/test-tls-set-ciphers.js

+5-4
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ test('TLS_AES_256_GCM_SHA384', U, 'TLS_AES_256_GCM_SHA384');
8888

8989
// Do not have shared ciphers.
9090
test('TLS_AES_256_GCM_SHA384', 'TLS_CHACHA20_POLY1305_SHA256',
91-
U, 'ECONNRESET', 'ERR_SSL_NO_SHARED_CIPHER');
91+
U, 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE', 'ERR_SSL_NO_SHARED_CIPHER');
9292

93-
test('AES128-SHA', 'AES256-SHA', U, 'ECONNRESET', 'ERR_SSL_NO_SHARED_CIPHER');
93+
test('AES128-SHA', 'AES256-SHA', U, 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE',
94+
'ERR_SSL_NO_SHARED_CIPHER');
9495
test('AES128-SHA:TLS_AES_256_GCM_SHA384',
9596
'TLS_CHACHA20_POLY1305_SHA256:AES256-SHA',
96-
U, 'ECONNRESET', 'ERR_SSL_NO_SHARED_CIPHER');
97+
U, 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE', 'ERR_SSL_NO_SHARED_CIPHER');
9798

9899
// Cipher order ignored, TLS1.3 chosen before TLS1.2.
99100
test('AES256-SHA:TLS_AES_256_GCM_SHA384', U, 'TLS_AES_256_GCM_SHA384');
@@ -109,7 +110,7 @@ test(U, 'AES256-SHA', 'TLS_AES_256_GCM_SHA384', U, U, { maxVersion: 'TLSv1.3' })
109110
// TLS_AES_128_CCM_8_SHA256 & TLS_AES_128_CCM_SHA256 are not enabled by
110111
// default, but work.
111112
test('TLS_AES_128_CCM_8_SHA256', U,
112-
U, 'ECONNRESET', 'ERR_SSL_NO_SHARED_CIPHER');
113+
U, 'ERR_SSL_SSLV3_ALERT_HANDSHAKE_FAILURE', 'ERR_SSL_NO_SHARED_CIPHER');
113114

114115
test('TLS_AES_128_CCM_8_SHA256', 'TLS_AES_128_CCM_8_SHA256',
115116
'TLS_AES_128_CCM_8_SHA256');

0 commit comments

Comments
 (0)