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

TLS/SSL: tls.TLSSocket emits error event on handshake failure #8805

Closed
wants to merge 2 commits into from

Conversation

lekoder
Copy link
Contributor

@lekoder lekoder commented Sep 27, 2016

Checklist
  • make -j8 test (UNIX), or vcbuild test nosign (Windows) passes *
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

tls/ssl

Description of change

tls.TLSSocket emits now error event on handshake failure.

Fixes #8803

Notes
  • upstream/master does not pass make -j8 test on time of this contribution - with unrelated errors. Tests related to tls/ssl and new test to highlight referenced issue pass.

@nodejs-github-bot nodejs-github-bot added the tls Issues and PRs related to the tls subsystem. label Sep 27, 2016
@@ -0,0 +1,31 @@
'use strict';
var common = require('../common');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: const

return;
}
var tls = require('tls');
var net = require('net');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const here also

@jasnell
Copy link
Member

jasnell commented Sep 27, 2016

Couple of nits. /cc @nodejs/streams for review

@mscdex
Copy link
Contributor

mscdex commented Sep 27, 2016

/cc @indutny ?

server: server
});

s.on('error', common.mustCall(function() {}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any validation you can add to the error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cjihrig quite right, added basic validation.

server.close();
s.destroy();
});
}), 200);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this must be common.platformTimeout based.

var bonkers = Buffer.alloc(1024, 42);

var server = net.createServer(common.mustCall(function(c) {
setTimeout(common.mustCall(function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need common.mustCall here, but it does not hurt either. Any other opinions?


var bonkers = Buffer.alloc(1024, 42);

var server = net.createServer(common.mustCall(function(c) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

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

var bonkers = Buffer.alloc(1024, 42);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

self.destroy(err);
} else {
self.destroy(self._tlsError(err));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not clear why this change fix the described issue. Can you please add a comment describing why?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Furthermore, _tlsError returns null if self._controlReleased === false. I don't see how this particular change makes it behave differently.

Copy link
Contributor Author

@lekoder lekoder Sep 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mcollina @indutny self._tlsError returning null is exactly what i am addressing here. When handshake fails and ssl.onerror is called control is not released yet, so self.destroy is called with null, and error event is not fired in destroy.

Here is debug output from upstream:

NET 26944: listen2 null 1337 4 false undefined
NET 26944: _listen2: create a handle
NET 26944: bind to ::
NET 26944: onconnection
NET 26944: _read
NET 26944: Socket._read readStart
NET 26944: _read
TLS 26944: onhandshakestart
NET 26944: destroy null
NET 26944: destroy
NET 26944: close
NET 26944: close handle
NET 26944: destroy undefined
NET 26944: destroy
NET 26944: close
NET 26944: close handle
NET 26944: has server
NET 26944: SERVER _emitCloseIfDrained
NET 26944: SERVER handle? true   connections? 0
NET 26944: emit close
NET 26944: emit close

...and here after the patch:

NET 31249: listen2 null 1337 4 0 undefined
NET 31249: _listen2: create a handle
NET 31249: bind to ::
NET 31249: onconnection
NET 31249: _read
NET 31249: Socket._read readStart
NET 31249: _read
TLS 31249: onhandshakestart
NET 31249: destroy Error: 140507750061888:error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher:../deps/openssl/openssl/ssl/s3_srvr.c:1418:

NET 31249: destroy
NET 31249: close
NET 31249: close handle
NET 31249: destroy undefined
NET 31249: destroy
NET 31249: close
NET 31249: close handle
NET 31249: has server
NET 31249: SERVER _emitCloseIfDrained
NET 31249: SERVER handle? true   connections? 0
NET 31249: emit close
NET 31249: emit close

Now, just replacing self.destroy(self._tlsError(err)) with self.destroy(err) there also fixes #8803 and same tests pass, but since self._tlsError emits additional '_tlsError' event which could be used in something not covered with tests, i opted for safer approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_tlsError is used for emitting tlsClientError, which is in turn used in https module to kill the request.

self.destroy(err);
} else {
self.destroy(self._tlsError(err));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Furthermore, _tlsError returns null if self._controlReleased === false. I don't see how this particular change makes it behave differently.

@lekoder
Copy link
Contributor Author

lekoder commented Sep 28, 2016

Confused. I rebased my branch to upstream/master as per step 4 of contributing guide, but it doesn't feel right now. Should i rebase it back?

@mcollina
Copy link
Member

@lekoder no it doesn't feel right. I think you might want to start clean and force push your individual changes here again.

Usually you rebase when you get some LGTMs, before it's merged.

@lekoder
Copy link
Contributor Author

lekoder commented Sep 29, 2016

@mcollina I did just that. I would suggest adding this info to contributing guide, ie:

note: Do not rebase your branch if you already made pull request.

@mcollina
Copy link
Member

@lekoder rebasing is fine, you might have made a mistake in the process. Your commits needs to sit on top of upstream master.

You should probably squash your commits into one.

@mcollina
Copy link
Member

I'm LGTM for the streams point of view, but @indutny has the final say.

server: server
});

s.on('error', common.mustCall(function(e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a case you fixing? Creating a socket manually for a server?

@indutny
Copy link
Member

indutny commented Sep 29, 2016

I had more time to think about it, and it looks like the patch is correct. Whilst reviewing things I have found that we have quite a funny possible infinite loop in error event handler... Going to fix it in a follow up PR.

Please reduce the branching code, and this PR will be good to go. Thank you!

@lekoder
Copy link
Contributor Author

lekoder commented Sep 30, 2016

@indutny Removed branch as suggested. Also added tests to make sure that tls.Server was not affected by that change (it wasn't, but i figured additional test won't hurt - i can drop it if you feel it's redundant).

Removes branch that would make TLSSocket emit '_tlsError' event if error occured on handshake and controll was not released, as it was never happening. Addedd test for tls.Server to ensure it still emits 'tlsClientError' as expected.

Makes tests conform to defined linting rules.
@lekoder lekoder force-pushed the tls-socket-emit-clienterror branch from 1c2a46c to d3027e8 Compare October 7, 2016 06:03
@lekoder
Copy link
Contributor Author

lekoder commented Oct 7, 2016

@mcollina I did some testing of the whole rebasing problem i had with. Problem was caused by doing:

$ git fetch upstream
$ git rebase upstream/master
$ git pull && git push

...and that ended up with pull request that contained not only my changes, but also all commits from upstream/master to this point. What did work:

$ git fetch upstream
$ git rebase upstream/master
$ git push -f

...or even better:

$ git fetch upstream
$ git rebase master upstream/master 
$ git push origin
$ git checkout my-branch
$ git rebase master
$ git push -f

...which makes my origin/master in sync with upstream/master, and my-branch based on that.

Copy link
Member

@indutny indutny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Sorry for delay!

@jasnell
Copy link
Member

jasnell commented Oct 7, 2016

@mcollina
Copy link
Member

Landed as c7bc9bc.

@mcollina mcollina closed this Oct 10, 2016
mcollina pushed a commit that referenced this pull request Oct 10, 2016
Removes branch that would make TLSSocket emit '_tlsError' event if error
occured on handshake and control was not released, as it was never happening.
Addedd test for tls.Server to ensure it still emits 'tlsClientError' as expected.

Fixes: #8803
PR-URL: #8805
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
jasnell pushed a commit that referenced this pull request Oct 10, 2016
Removes branch that would make TLSSocket emit '_tlsError' event if error
occured on handshake and control was not released, as it was never happening.
Addedd test for tls.Server to ensure it still emits 'tlsClientError' as expected.

Fixes: #8803
PR-URL: #8805
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
Fishrock123 pushed a commit that referenced this pull request Oct 11, 2016
Removes branch that would make TLSSocket emit '_tlsError' event if error
occured on handshake and control was not released, as it was never happening.
Addedd test for tls.Server to ensure it still emits 'tlsClientError' as expected.

Fixes: #8803
PR-URL: #8805
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
@MylesBorins
Copy link
Contributor

when backporting to v4.x we get some failing tests

=== release test-tls-server-failed-handshake-emits-clienterror ===
Path: parallel/test-tls-server-failed-handshake-emits-clienterror
assert.js:85
  throw new assert.AssertionError({
  ^
AssertionError: tlsClientError should be emited
    at null._onTimeout (/Users/thealphanerd/code/node/v4.x/test/parallel/test-tls-server-failed-handshake-emits-clienterror.js:34:10)
    at Timer.listOnTimeout (timers.js:92:15)
Command: out/Release/node /Users/thealphanerd/code/node/v4.x/test/parallel/test-tls-server-failed-handshake-emits-clienterror.js

Would someone be willing to manually backport

@bnoordhuis
Copy link
Member

I'll take a look.

bnoordhuis pushed a commit to bnoordhuis/io.js that referenced this pull request Nov 22, 2016
Removes branch that would make TLSSocket emit '_tlsError' event if
error occured on handshake and control was not released, as it was
never happening.  Added test for tls.Server to ensure it still emits
'tlsClientError' as expected.

Note that 'tlsClientError' does not exist in the v4.x branch so this
back-port emits 'clientError' instead.  See also pull request nodejs#4557.

Fixes: nodejs#8803
PR-URL: nodejs#8805
Refs: nodejs#4557
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
@bnoordhuis
Copy link
Member

#9742 - 'tlsClientError' wasn't introduced until v6.x, it emits 'clientError' instead.

MylesBorins pushed a commit that referenced this pull request Mar 28, 2017
Removes branch that would make TLSSocket emit '_tlsError' event if
error occured on handshake and control was not released, as it was
never happening.  Added test for tls.Server to ensure it still emits
'tlsClientError' as expected.

Note that 'tlsClientError' does not exist in the v4.x branch so this
back-port emits 'clientError' instead.  See also pull request #4557.

Fixes: #8803
PR-URL: #8805
Refs: #4557
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
MylesBorins pushed a commit that referenced this pull request Apr 4, 2017
Removes branch that would make TLSSocket emit '_tlsError' event if
error occured on handshake and control was not released, as it was
never happening.  Added test for tls.Server to ensure it still emits
'tlsClientError' as expected.

Note that 'tlsClientError' does not exist in the v4.x branch so this
back-port emits 'clientError' instead.  See also pull request #4557.

Fixes: #8803
PR-URL: #8805
Refs: #4557
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
MylesBorins pushed a commit that referenced this pull request Apr 17, 2017
Removes branch that would make TLSSocket emit '_tlsError' event if
error occured on handshake and control was not released, as it was
never happening.  Added test for tls.Server to ensure it still emits
'tlsClientError' as expected.

Note that 'tlsClientError' does not exist in the v4.x branch so this
back-port emits 'clientError' instead.  See also pull request #4557.

Fixes: #8803
PR-URL: #8805
Refs: #4557
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
MylesBorins pushed a commit that referenced this pull request Apr 19, 2017
Removes branch that would make TLSSocket emit '_tlsError' event if
error occured on handshake and control was not released, as it was
never happening.  Added test for tls.Server to ensure it still emits
'tlsClientError' as expected.

Note that 'tlsClientError' does not exist in the v4.x branch so this
back-port emits 'clientError' instead.  See also pull request #4557.

Fixes: #8803
PR-URL: #8805
Refs: #4557
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Fedor Indutny <fedor@indutny.com>
@MylesBorins MylesBorins mentioned this pull request Apr 19, 2017
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

Successfully merging this pull request may close these issues.

9 participants