Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request 2.65.0 getPeerCertificate() always returns null on node 4.2.1, works on 0.12.7 #3545

Closed
mikemaccana opened this issue Oct 27, 2015 · 13 comments
Labels
tls Issues and PRs related to the tls subsystem.

Comments

@mikemaccana
Copy link
Contributor

This seems to be a regression between node 4.2.1 and node 0.1.2:

var request = require('request')
request({
  url: 'https://github.com'
}, function (err, res, body) {
  console.log('err', err)
  console.log('peerCertificate:',res.req.connection.getPeerCertificate());
  console.log('authorized:',res.req.connection.authorized);
  console.log('authorizationError:',res.req.connection.authorizationError);
});

First node 0.12.7:

# grep ver node_modules/request/package.json
  "version": "2.65.0"

# node --version
v0.12.7

# node testssl.js
err null
peerCertificate: { subject:
   { businessCategory: 'Private Organization',
     '1.3.6.1.4.1.311.60.2.1.3': 'US',
     '1.3.6.1.4.1.311.60.2.1.2': 'Delaware',
     serialNumber: '5157550',
     street: '548 4th Street',
     postalCode: '94107',
     C: 'US',
     ST: 'California',
     L: 'San Francisco',
     O: 'GitHub, Inc.',
     CN: 'github.com' }

     ...

Then node 4.2.1:

# node --version
v4.2.1

# grep ver node_modules/request/package.json
  "version": "2.65.0"

# node testssl.js
err null
peerCertificate: null
authorized: true
authorizationError: null
@bnoordhuis
Copy link
Member

Do you also see it when you use the https or tls module directly? request is a third-party library.

@bnoordhuis
Copy link
Member

WFM with master, by the way:

$ out/Release/node -e 'require("tls").connect(443, "github.com", function() { console.log(this.getPeerCertificate()) })'
{ subject: 
   { businessCategory: 'Private Organization',
     jurisdictionC: 'US',
     jurisdictionST: 'Delaware',
     serialNumber: '5157550',
     street: '548 4th Street',
     postalCode: '94107',
     C: 'US',
     ST: 'California',
     L: 'San Francisco',
     O: 'GitHub, Inc.',
     CN: 'github.com' },
  issuer: 
   { C: 'US',
     O: 'DigiCert Inc',
     OU: 'www.digicert.com',
     CN: 'DigiCert SHA2 Extended Validation Server CA' },
  subjectaltname: 'DNS:github.com, DNS:www.github.com',
  infoAccess: 
   { 'OCSP - URI': [ 'http://ocsp.digicert.com' ],
     'CA Issuers - URI': [ 'http://cacerts.digicert.com/DigiCertSHA2ExtendedValidationServerCA.crt' ] },
  modulus: 'B1D4DC3CAFFDF34EEDC167ADE6CB22E8B7E2AB28F2F7DC627008D10CAFD6166A21B0364B170D366304AEBFEA2051956566F2BFB94DA40C29EBF515B1E835B3701094D51B59B4260FD68357599DE17C09DDE013CA4D6F439BCDCF873A15A785DD6683ED930CFE2B6D381C798890CFAD58182D51D1C2A3F2478C6F3809B9B8EF4C930BCB839487EAE0A3B5D97B9B6B0F43F9CAEE800D28A776F125F4C1353CF674ADDE6A33827BDCFD4B76A7C2EEF26ABFA924A65FE72E7C0EDBC37473FA7EC6D8CF60EB365621B6C18AB824824D7824BAE91DA18AA787BE662569BFBE3B726E4FE0E4852508B19189B8D67465769B2C4F621FA1FA3ABE9C24BF9FCAB0C5C0678D',
  exponent: '0x10001',
  valid_from: 'Apr  8 00:00:00 2014 GMT',
  valid_to: 'Apr 12 12:00:00 2016 GMT',
  fingerprint: 'A0:C4:A7:46:00:ED:A7:2D:C0:BE:CB:9A:8C:B6:07:CA:58:EE:74:5E',
  ext_key_usage: [ '1.3.6.1.5.5.7.3.1', '1.3.6.1.5.5.7.3.2' ],
  serialNumber: '0C009310D206DBE337553580118DDC87',
  raw: <Buffer 30 82 05 e0 30 82 04 c8 a0 03 02 01 02 02 10 0c 00 93 10 d2 06 db e3 37 55 35 80 11 8d dc 87 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 75 31 0b ... > }
^C

@mikemaccana
Copy link
Contributor Author

Thanks @bnoordhuis! Yep tls is fine here. I'd thought it was a node issue since the request version is the same, but given that the tls module itself is fine it looks like this is a request issue?

@mikemaccana
Copy link
Contributor Author

Moving to request: request/request#1867

@DaftMonk
Copy link
Contributor

DaftMonk commented Nov 8, 2015

After some digging through the request source code, I don't believe the issue is with request.

In node 4.2.1, after the response connection is closed (once the close event is fired on the IncomingMessage), getPeerCertificate returns null. However, if you call getPeerCertificate before the response is closed, it returns the peer certificate as expected.

In node 0.12.x, calling getPeerCertificate even after the connection has closed returns the peer certificate.

This seem to be a regression between node 0.12 and 4.x (or maybe an intentional change that isn't clearly documented), and is especially noticeable with the request library, because the request callback is always called after the connection has been closed.

One workaround is to grab the response before the close event is fired. You can do this like so:

var request = require('request')

var r = request({
  url: 'https://github.com'
});

r.on('response', function(res) {
  console.log(res.req.connection.getPeerCertificate()) // works
})

@bnoordhuis
Copy link
Member

I can confirm that .getPeerCertificate() works after close with v0.10 and v0.12 but not v4.x+. Test case:

var c = require('tls').connect(443, 'github.com', function() { this.destroy() });
c.once('close', function() { console.log(this.getPeerCertificate()) });

/cc @indutny - No opinion on whether it's a good idea to bring back the old behavior. I'm not sure from looking at the code it that's feasible without negating the memory savings.

@bnoordhuis bnoordhuis reopened this Nov 9, 2015
@bnoordhuis bnoordhuis added the tls Issues and PRs related to the tls subsystem. label Nov 9, 2015
@indutny
Copy link
Member

indutny commented Nov 10, 2015

@bnoordhuis this is rather unfortunate and fortunate at the same time. This gave us a pretty solid cut off in RSS usage. I think we could introduce an option to keep the SSL instance alive after close, but it will come at the increased memory usage cost.

Will this work for you, @mikemaccana ?

@bnoordhuis
Copy link
Member

I would lean towards just documenting it. I don't think we need more complexity in the tls module and the current behavior doesn't strike me as unreasonable: Connection closed? Then so is the TLS metadata.

It's unfortunate this slipped through but it's not as if the old behavior was documented or even intentional (witness the paucity of regression tests for this feature.) It was just an accident of the implementation.

@indutny
Copy link
Member

indutny commented Nov 10, 2015

Sounds about right @bnoordhuis . Is anyone interested in contributing this? ;)

@DaftMonk
Copy link
Contributor

I'll write something for it a bit later.

@mikemaccana
Copy link
Contributor Author

Ditto. As long as the correct approach is documented (eg, holding connection open it seems) in happy.

@mikemaccana
Copy link
Contributor Author

I'm, ahem.

@bnoordhuis
Copy link
Member

Documented in eff8c3e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tls Issues and PRs related to the tls subsystem.
Projects
None yet
Development

No branches or pull requests

4 participants