Skip to content

Commit 20c1ede

Browse files
author
Shigeki Ohtsu
committed
tls_wrap: fix error cb when fatal TLS Alert recvd
SSL_read() returns 0 when fatal TLS Alert is received. Fix to invoke ssl error callback in this case.
1 parent 56129de commit 20c1ede

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

src/tls_wrap.cc

+8-1
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ void TLSWrap::EncOutCb(WriteWrap* req_wrap, int status) {
352352
Local<Value> TLSWrap::GetSSLError(int status, int* err, const char** msg) {
353353
EscapableHandleScope scope(env()->isolate());
354354

355+
// ssl_ is already destroyed in reading EOF by close notify alert.
356+
if (ssl_ == nullptr)
357+
return Local<Value>();
358+
355359
*err = SSL_get_error(ssl_, status);
356360
switch (*err) {
357361
case SSL_ERROR_NONE:
@@ -432,7 +436,10 @@ void TLSWrap::ClearOut() {
432436
OnRead(UV_EOF, nullptr);
433437
}
434438

435-
if (read == -1) {
439+
// We need to check whether an error occurred or the connection was
440+
// shutdown cleanly (SSL_ERROR_ZERO_RETURN) even when read == 0.
441+
// See iojs#1642 and SSL_read(3SSL) for details.
442+
if (read <= 0) {
436443
int err;
437444
Local<Value> arg = GetSSLError(read, &err, nullptr);
438445

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
var common = require('../common');
2+
var assert = require('assert');
3+
4+
if (!common.opensslCli) {
5+
console.error('Skipping because node compiled without OpenSSL CLI.');
6+
process.exit(0);
7+
}
8+
9+
if (!common.hasCrypto) {
10+
console.log('1..0 # Skipped: missing crypto');
11+
process.exit();
12+
}
13+
14+
var tls = require('tls');
15+
var net = require('net');
16+
var fs = require('fs');
17+
18+
var success = false;
19+
20+
function filenamePEM(n) {
21+
return require('path').join(common.fixturesDir, 'keys', n + '.pem');
22+
}
23+
24+
function loadPEM(n) {
25+
return fs.readFileSync(filenamePEM(n));
26+
}
27+
28+
var opts = {
29+
key: loadPEM('agent2-key'),
30+
cert: loadPEM('agent2-cert')
31+
};
32+
33+
var max_iter = 20;
34+
var iter = 0;
35+
36+
var server = tls.createServer(opts, function(s) {
37+
s.pipe(s);
38+
s.on('error', function(e) {
39+
// ignore error
40+
});
41+
});
42+
43+
server.listen(common.PORT, function() {
44+
sendClient();
45+
});
46+
47+
48+
function sendClient() {
49+
var client = tls.connect(common.PORT, {
50+
rejectUnauthorized: false
51+
});
52+
client.on('data', function(chunk) {
53+
if (iter++ === 2) sendBADTLSRecord();
54+
if (iter < max_iter) {
55+
client.write('a');
56+
return;
57+
}
58+
client.end();
59+
server.close();
60+
success = true;
61+
});
62+
client.write('a');
63+
client.on('error', function(e) {
64+
// ignore error
65+
});
66+
client.on('close', function() {
67+
server.close();
68+
});
69+
}
70+
71+
72+
function sendBADTLSRecord() {
73+
var BAD_RECORD = new Buffer([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
74+
var socket = net.connect(common.PORT);
75+
var client = tls.connect({
76+
socket: socket,
77+
rejectUnauthorized: false
78+
}, function() {
79+
socket.write(BAD_RECORD);
80+
socket.end();
81+
});
82+
client.on('error', function(e) {
83+
// ignore error
84+
});
85+
}
86+
87+
process.on('exit', function() {
88+
assert(iter === max_iter);
89+
assert(success);
90+
});

0 commit comments

Comments
 (0)