Sitelet https://github.com/nodejs/node/issues/867
Skip to content

Malformed crt with HTTPS SNI causes hang - no error, no result #867

Description

@coolaj86

This just hangs without throwing an error or completing the request:

curl https://localhost:65443 -k

Expected result

client receives

Cannot GET /

server logs

[log] SNI: local.helloworld3000.com
[log] SNI: undefined
[log] {}
[log] request
[log] request for local.helloworld3000.com:65443/

Reduced Test Case

'use strict';

var https           = require('https');
var fs              = require('fs');
var path            = require('path');
var crypto          = require('crypto');
var connect         = require('connect');

module.exports.create = function (_securePort, _insecurePort) {
    // connect / express app
  var app             = connect();

    // SSL Server
  var secureContexts  = {};
  var dummyCerts;
  var secureOpts;
  var secureServer;
  var securePort      = _securePort || 443;

    // force SSL upgrade server
  var insecureServer;
  var insecurePort    = _insecurePort || 80;

  function loadDummyCerts() {
    var certsPath = path.join(__dirname, 'certs');
    var certs = {
      key:          fs.readFileSync(path.join(certsPath, 'server', 'dummy-server.key.pem'))
    , cert:         fs.readFileSync(path.join(certsPath, 'server', 'dummy-server.crt.pem'))
    , ca:           fs.readdirSync(path.join(certsPath, 'ca')).map(function (node) {
                      return fs.readFileSync(path.join(certsPath, 'ca', node));
                    })
    };
    secureContexts.dummy = crypto.createCredentials(certs).context;
    dummyCerts = certs;
  }
  loadDummyCerts();

  app.use(function (req, res, next) {
    console.log('[log] request for ' + req.headers.host + req.url);
    next();
  });

  function runServer() {
    //provide a SNICallback when you create the options for the https server
    secureOpts = {
      //SNICallback is passed the domain name, see NodeJS docs on TLS
      SNICallback:  function (domainname) {
                      console.log('[log] SNI:', domainname);
                      console.log('[log] SNI:', secureContexts[domainname]);
                      var secureContext = secureContexts[domainname] || secureContexts.dummy;
                      console.log('[log]', secureContext);
                      return secureContext;
                    }
                    // fallback / default dummy certs
    , key:          dummyCerts.key
    , cert:         dummyCerts.cert
    , ca:           dummyCerts.ca
    };

    secureServer = https.createServer(secureOpts);
    secureServer.on('request', function (req, res) {
      console.log('[log] request');
      app(req, res);
    });
    secureServer.listen(securePort, function () {
      console.log("Listening on https://localhost:" + secureServer.address().port);
    });
  }

  runServer();
}
module.exports.create(443, 80);

directory layout

tree
├── vhost-sni-server.js
├── certs
│   ├── ca
│   │   ├── dummy-root-ca.crt.pem
│   │   ├── my-root-ca.crt.pem
│   │   └── my-root-ca.key.pem
│   ├── README.md
│   └── server
│       ├── dummy-server.crt.pem
│       ├── dummy-server.key.pem
│       ├── my-server.crt.pem
│       └── my-server.key.pem

Activity

  1. coolaj86 commented on Feb 17, 2015

    @coolaj86
    Author

    Confirmed broken in

    • v0.12.0 on OS X
    • v1.2.0 on OS X
    • v1.2.0 on ARM6

    Confirmed working in

    • v0.10.36 on OS X
    • v0.10.36 on ARM6

    Perhaps there's an API change that I'm unaware of? If so it seems like this should throw an error, not just hang.

  2. changed the title [-]HTTPS SNI broken on arm6l (maybe others as well)[/-] [+]Using HTTPS SNI causes hang - no error, no result[/+] on Feb 17, 2015
  3. changed the title [-]Using HTTPS SNI causes hang - no error, no result[/-] [+]Malformed crt with HTTPS SNI causes hang - no error, no result[/+] on Feb 17, 2015
  4. coolaj86 commented on Feb 17, 2015

    @coolaj86
    Author

    Okay, so v0.10.36 has a flaw that allows it to work - it ignores the key file instead of erroring on it. A key file, obviously, should not get loaded into the CA chain.

    node.js / io.js latest have the flaw that although they don't work with a key file in the chain (good), they don't give an error or any indication of what went wrong.

    After removing the key file that was in the wrong place:

    ├── vhost-sni-server.js
    ├── certs
    │   ├── ca
    │   │   ├── dummy-root-ca.crt.pem
    │   │   └── my-root-ca.crt.pem
    │   ├── README.md
    │   └── server
    │       ├── dummy-server.crt.pem
    │       ├── dummy-server.key.pem
    │       ├── my-server.crt.pem
    │       └── my-server.key.pem
    

    It works.

    # using the name on the cert
    curl https://local.helloworld3000.com:65443 --cacert certs/ca/dummy-root-ca.crt.pem
    > Cannot GET /
    
    # using insecure
    curl https://localhost:65443 -k
    > Cannot GET /
    

    I can upload the exact certs that I'm using upon request. They're all test / dummy certs anyway, so no risk there.

  5. coolaj86 commented on Feb 17, 2015

    @coolaj86
    Author

    Hmm... my workaround didn't work on ARM, only on OS X. There's still something wrong...

  6. Fishrock123 commented on Feb 26, 2015

    @Fishrock123
    Contributor

    @coolaj86 are you still experiencing this? cc @indutny?

  7. coolaj86 commented on Feb 26, 2015

    @coolaj86
    Author

    It only happens when I return the crts immediately (not using the optional callback) AND there's a malformed crt (aka a key) in the chain.

    If I use the callback or I take out the bad crt it works as expected (except I don't remember if using the callback sends an error or silently ignores the key).

    And it happens on OS X, but on Raspberry Pi returning immediately doesn't work at all anyway.

    I'd have to reinstall v1.2 or master to be certain, but I had a test case On v1.2 at the time I created the issue.

  8. indutny commented on Feb 26, 2015

    @indutny
    Member

    @coolaj86 returning context is not supported anymore, I'm not sure how it could be working :)

  9. coolaj86 commented on Feb 26, 2015

    @coolaj86
    Author

    Maybe I had my node versions mixed up. Maybe I was actually on 0.11.

    In that case, sorry for the noise, I'll close this and the related issue and reopen if I can reconfirm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions