Skip to content

Commit

Permalink
tls_wrap: fix error cb when fatal TLS Alert recvd
Browse files Browse the repository at this point in the history
SSL_read() returns 0 when fatal TLS Alert is received.
Fix to invoke ssl error callback in this case.
  • Loading branch information
Shigeki Ohtsu committed May 12, 2015
1 parent 56129de commit 20c1ede
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/tls_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,10 @@ void TLSWrap::EncOutCb(WriteWrap* req_wrap, int status) {
Local<Value> TLSWrap::GetSSLError(int status, int* err, const char** msg) {
EscapableHandleScope scope(env()->isolate());

// ssl_ is already destroyed in reading EOF by close notify alert.
if (ssl_ == nullptr)
return Local<Value>();

*err = SSL_get_error(ssl_, status);
switch (*err) {
case SSL_ERROR_NONE:
Expand Down Expand Up @@ -432,7 +436,10 @@ void TLSWrap::ClearOut() {
OnRead(UV_EOF, nullptr);
}

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

Expand Down
90 changes: 90 additions & 0 deletions test/parallel/test-tls-alert-handling.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
var common = require('../common');
var assert = require('assert');

if (!common.opensslCli) {
console.error('Skipping because node compiled without OpenSSL CLI.');
process.exit(0);
}

if (!common.hasCrypto) {
console.log('1..0 # Skipped: missing crypto');
process.exit();
}

var tls = require('tls');
var net = require('net');
var fs = require('fs');

var success = false;

function filenamePEM(n) {
return require('path').join(common.fixturesDir, 'keys', n + '.pem');
}

function loadPEM(n) {
return fs.readFileSync(filenamePEM(n));
}

var opts = {
key: loadPEM('agent2-key'),
cert: loadPEM('agent2-cert')
};

var max_iter = 20;
var iter = 0;

var server = tls.createServer(opts, function(s) {
s.pipe(s);
s.on('error', function(e) {
// ignore error
});
});

server.listen(common.PORT, function() {
sendClient();
});


function sendClient() {
var client = tls.connect(common.PORT, {
rejectUnauthorized: false
});
client.on('data', function(chunk) {
if (iter++ === 2) sendBADTLSRecord();
if (iter < max_iter) {
client.write('a');
return;
}
client.end();
server.close();
success = true;
});
client.write('a');
client.on('error', function(e) {
// ignore error
});
client.on('close', function() {
server.close();
});
}


function sendBADTLSRecord() {
var BAD_RECORD = new Buffer([0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
var socket = net.connect(common.PORT);
var client = tls.connect({
socket: socket,
rejectUnauthorized: false
}, function() {
socket.write(BAD_RECORD);
socket.end();
});
client.on('error', function(e) {
// ignore error
});
}

process.on('exit', function() {
assert(iter === max_iter);
assert(success);
});

0 comments on commit 20c1ede

Please sign in to comment.