clientError emitted for wrong socket - SSL alert number 48
NOTE: The following bug report was originally submitted to the node team at https://github.com/joyent/node/issues/14818; however, I encountered the same issue in io.js when trying it out. I have been able to reproduce the issue on io.js compiled from source from the master branch (v2.0.1), both on my Arch desktop and Debian server. It's worth noting that the issue does not occur on the v0.10 branch of node.js, only the v0.12 branch.
I've noticed a peculiar behavior of the https
module with regard to Firefox closing connections for untrusted certificates. In the demo below, I use a self-signed certificate generated by the pem
module, but the same principle can be applied to any untrusted certificate (for example, I was able to cause the same issue by deleting the Startcom signing certificates from Firefox and attempting to connect to a server with a StartSSL cert).
What happens is that as soon as a Firefox client that doesn't trust the certificate terminates its connection, the https
server fires a clientError
event with an SSL error-- except this event is fired on a random socket that has no relation to the Firefox client. I determined this by gathering several different Chrome users, having them all connect to a server I controlled, and observing the errors logged when I connect with Firefox.
I would expect instead that the socket
parameter passed to the clientError
event handler would be the client that triggered the error, not some arbitrary other client.
Steps to reproduce:
-
Download server.js and index.html as listed below
-
Install the
pem
module -
Start the server, and navigate Chromium to
https://localhost:4444
- Click Advanced and Proceed to localhost (unsafe)
-
Navigate Firefox to
https://localhost:4444
-
Observe that as soon as the Untrusted Connection page displays in Firefox, a
clientError
is triggered on the server, but on the Chromium client:Error: 140173278586688:error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:s3_pkt.c:1461:SSL alert number 48 at Error (native) Triggered on client with UA: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36
Demo:
server.js
var https = require('https');
var pem = require('pem');
var fs = require('fs');
var indexHtml = fs.readFileSync('index.html');
pem.createCertificate({ days: 10, selfSigned: true }, function (err, keys) {
if (err) throw err;
var httpServer = https.createServer({
key: keys.serviceKey,
cert: keys.certificate
}, function (req, res) {
req.socket.userAgent = req.headers['user-agent'];
res.writeHead('200', {
'Content-Type': 'text/html',
'Content-Length': indexHtml.length
});
res.end(indexHtml);
});
httpServer.on('clientError', function (err, socket) {
console.log(err.stack);
console.log('Triggered on client with UA: ' + socket.userAgent);
});
httpServer.listen(4444);
});
index.html
<!doctype html>
<html lang="en">
<head>
<title>SSL Error Demo</title>
<meta charset="utf-8">
</head>
<body>
<div id="debug"></div>
<script type="text/javascript">
function makeRequest() {
var req = new XMLHttpRequest();
req.open('GET', location.href, true);
req.onload = function (ev) {
setTimeout(makeRequest, 10);
};
req.send();
}
makeRequest();
</script>
</body>
</html>