tls_wrap: use localhost if options.host is empty
authorGuilherme Souza <sitegui@sitegui.com.br>
Tue, 21 Apr 2015 21:24:13 +0000 (18:24 -0300)
committerRoman Reiss <me@silverwind.io>
Thu, 23 Apr 2015 14:54:11 +0000 (16:54 +0200)
tls.connect(options) with no options.host should accept a certificate
with CN: 'localhost'. Fix Error: Hostname/IP doesn't match
certificate's altnames: "Host: undefined. is not cert's CN: localhost"

'localhost' is not added directly to defaults because that is not
always desired (for example, when using options.socket)

PR-URL: https://github.com/iojs/io.js/pull/1493
Fixes: https://github.com/iojs/io.js/issues/1489
Reviewed-By: Brendan Ashworth <brendan.ashworth@me.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
lib/_tls_wrap.js
test/parallel/test-tls-connect-no-host.js [new file with mode: 0644]

index 3e091b0..c1037a7 100644 (file)
@@ -858,7 +858,8 @@ exports.connect = function(/* [port, host], options, cb */) {
 
   var hostname = options.servername ||
                  options.host ||
-                 options.socket && options.socket._host,
+                 (options.socket && options.socket._host) ||
+                 'localhost',
       NPN = {},
       context = tls.createSecureContext(options);
   tls.convertNPNProtocols(options.NPNProtocols, NPN);
diff --git a/test/parallel/test-tls-connect-no-host.js b/test/parallel/test-tls-connect-no-host.js
new file mode 100644 (file)
index 0000000..41aac1a
--- /dev/null
@@ -0,0 +1,34 @@
+var common = require('../common');
+
+if (!common.hasCrypto) {
+  console.log('1..0 # Skipped: missing crypto');
+  process.exit();
+}
+var tls = require('tls');
+
+var assert = require('assert');
+var fs = require('fs');
+var path = require('path');
+
+var cert = fs.readFileSync(path.join(common.fixturesDir, 'test_cert.pem'));
+var key = fs.readFileSync(path.join(common.fixturesDir, 'test_key.pem'));
+
+// https://github.com/iojs/io.js/issues/1489
+// tls.connect(options) with no options.host should accept a cert with
+//   CN:'localhost'
+tls.createServer({
+  key: key,
+  cert: cert
+}).listen(common.PORT);
+
+var socket = tls.connect({
+    port: common.PORT,
+    ca: cert,
+    // No host set here. 'localhost' is the default,
+    // but tls.checkServerIdentity() breaks before the fix with:
+    // Error: Hostname/IP doesn't match certificate's altnames:
+    //   "Host: undefined. is not cert's CN: localhost"
+}, function() {
+    assert(socket.authorized);
+    process.exit();
+});