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 wild card check supports for port #20875

Closed
wants to merge 1 commit into from
Closed

Conversation

shiup
Copy link

@shiup shiup commented May 22, 2018

If wild card dns check (both CN, or SAN) does not
contain port, it applies to all ports on the server.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  SOLINK_MODULE(target) Release/test_uv_loop.node
touch test/addons-napi/.buildstamp
/Applications/Xcode.app/Contents/Developer/usr/bin/make cctest
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C out BUILDTYPE=Release V=1
  touch 14bc63f62e96cfbc513dcfa609a1cd109c24d103.intermediate
  LD_LIBRARY_PATH=/Users/spoon/sfp/node/out/Release/lib.host:/Users/spoon/sfp/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /Users/spoon/sfp/node/out/Release/obj/gen/src/node/inspector/protocol; python deps/v8/third_party/inspector_protocol/CodeGenerator.py --jinja_dir deps/v8/third_party/inspector_protocol/.. --output_base "/Users/spoon/sfp/node/out/Release/obj/gen/src/" --config "/Users/spoon/sfp/node/out/Release/obj/gen/node_protocol_config.json"
  touch 3bc6331644efa748b7c8a3f9d879d754c4289033.intermediate
  LD_LIBRARY_PATH=/Users/spoon/sfp/node/out/Release/lib.host:/Users/spoon/sfp/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../deps/v8/gypfiles; mkdir -p /Users/spoon/sfp/node/out/Release/obj/gen/src/inspector/protocol /Users/spoon/sfp/node/out/Release/obj/gen/include/inspector; python ../third_party/inspector_protocol/CodeGenerator.py --jinja_dir ../third_party --output_base "/Users/spoon/sfp/node/out/Release/obj/gen/src/inspector" --config ../src/inspector/inspector_protocol_config.json
rm 14bc63f62e96cfbc513dcfa609a1cd109c24d103.intermediate 3bc6331644efa748b7c8a3f9d879d754c4289033.intermediate
if [ ! -r node -o ! -L node ]; then ln -fs out/Release/node node; fi
[==========] Running 74 tests from 9 test cases.
[----------] Global test environment set-up.
[----------] 14 tests from AliasBufferTest
[ RUN      ] AliasBufferTest.Uint8Array
[       OK ] AliasBufferTest.Uint8Array (15 ms)
[ RUN      ] AliasBufferTest.Int8Array
[       OK ] AliasBufferTest.Int8Array (7 ms)
[ RUN      ] AliasBufferTest.Uint16Array
[       OK ] AliasBufferTest.Uint16Array (7 ms)
[ RUN      ] AliasBufferTest.Int16Array
[       OK ] AliasBufferTest.Int16Array (7 ms)
[ RUN      ] AliasBufferTest.Uint32Array
[       OK ] AliasBufferTest.Uint32Array (8 ms)
[ RUN      ] AliasBufferTest.Int32Array
[       OK ] AliasBufferTest.Int32Array (8 ms)
[ RUN      ] AliasBufferTest.Float32Array
[       OK ] AliasBufferTest.Float32Array (8 ms)
[ RUN      ] AliasBufferTest.Float64Array
[       OK ] AliasBufferTest.Float64Array (6 ms)
[ RUN      ] AliasBufferTest.SharedArrayBuffer1
[       OK ] AliasBufferTest.SharedArrayBuffer1 (8 ms)
[ RUN      ] AliasBufferTest.SharedArrayBuffer2
[       OK ] AliasBufferTest.SharedArrayBuffer2 (8 ms)
[ RUN      ] AliasBufferTest.SharedArrayBuffer3
[       OK ] AliasBufferTest.SharedArrayBuffer3 (8 ms)
[ RUN      ] AliasBufferTest.SharedArrayBuffer4
[       OK ] AliasBufferTest.SharedArrayBuffer4 (7 ms)
[ RUN      ] AliasBufferTest.OperatorOverloads
[       OK ] AliasBufferTest.OperatorOverloads (8 ms)
[ RUN      ] AliasBufferTest.OperatorOverloadsRefs
[       OK ] AliasBufferTest.OperatorOverloadsRefs (8 ms)
[----------] 14 tests from AliasBufferTest (113 ms total)

[----------] 2 tests from Base64Test
[ RUN      ] Base64Test.Encode
[       OK ] Base64Test.Encode (0 ms)
[ RUN      ] Base64Test.Decode
[       OK ] Base64Test.Decode (0 ms)
[----------] 2 tests from Base64Test (0 ms total)

[----------] 7 tests from DebugSymbolsTest
[ RUN      ] DebugSymbolsTest.ContextEmbedderEnvironmentIndex
[       OK ] DebugSymbolsTest.ContextEmbedderEnvironmentIndex (7 ms)
[ RUN      ] DebugSymbolsTest.ExternalStringDataOffset
[       OK ] DebugSymbolsTest.ExternalStringDataOffset (8 ms)
[ RUN      ] DebugSymbolsTest.BaseObjectPersistentHandle
[       OK ] DebugSymbolsTest.BaseObjectPersistentHandle (8 ms)
[ RUN      ] DebugSymbolsTest.EnvironmentHandleWrapQueue
[       OK ] DebugSymbolsTest.EnvironmentHandleWrapQueue (7 ms)
[ RUN      ] DebugSymbolsTest.EnvironmentReqWrapQueue
[       OK ] DebugSymbolsTest.EnvironmentReqWrapQueue (8 ms)
[ RUN      ] DebugSymbolsTest.HandleWrapList
[       OK ] DebugSymbolsTest.HandleWrapList (8 ms)
[ RUN      ] DebugSymbolsTest.ReqWrapList
[       OK ] DebugSymbolsTest.ReqWrapList (10 ms)
[----------] 7 tests from DebugSymbolsTest (57 ms total)

[----------] 4 tests from EnvironmentTest
[ RUN      ] EnvironmentTest.AtExitWithEnvironment
[       OK ] EnvironmentTest.AtExitWithEnvironment (8 ms)
[ RUN      ] EnvironmentTest.AtExitWithoutEnvironment
[       OK ] EnvironmentTest.AtExitWithoutEnvironment (8 ms)
[ RUN      ] EnvironmentTest.AtExitWithArgument
[       OK ] EnvironmentTest.AtExitWithArgument (7 ms)
[ RUN      ] EnvironmentTest.MultipleEnvironmentsPerIsolate
[       OK ] EnvironmentTest.MultipleEnvironmentsPerIsolate (8 ms)
[----------] 4 tests from EnvironmentTest (31 ms total)

[----------] 1 test from PlatformTest
[ RUN      ] PlatformTest.SkipNewTasksInFlushForegroundTasks
[       OK ] PlatformTest.SkipNewTasksInFlushForegroundTasks (8 ms)
[----------] 1 test from PlatformTest (8 ms total)

[----------] 9 tests from UtilTest
[ RUN      ] UtilTest.ListHead
[       OK ] UtilTest.ListHead (0 ms)
[ RUN      ] UtilTest.StringEqualNoCase
[       OK ] UtilTest.StringEqualNoCase (0 ms)
[ RUN      ] UtilTest.StringEqualNoCaseN
[       OK ] UtilTest.StringEqualNoCaseN (0 ms)
[ RUN      ] UtilTest.ToLower
[       OK ] UtilTest.ToLower (0 ms)
[ RUN      ] UtilTest.Malloc
[       OK ] UtilTest.Malloc (0 ms)
[ RUN      ] UtilTest.Calloc
[       OK ] UtilTest.Calloc (0 ms)
[ RUN      ] UtilTest.UncheckedMalloc
[       OK ] UtilTest.UncheckedMalloc (0 ms)
[ RUN      ] UtilTest.UncheckedCalloc
[       OK ] UtilTest.UncheckedCalloc (0 ms)
[ RUN      ] UtilTest.MaybeStackBuffer
[       OK ] UtilTest.MaybeStackBuffer (0 ms)
[----------] 9 tests from UtilTest (0 ms total)

[----------] 7 tests from URLTest
[ RUN      ] URLTest.Simple
[       OK ] URLTest.Simple (1 ms)
[ RUN      ] URLTest.Simple2
[       OK ] URLTest.Simple2 (0 ms)
[ RUN      ] URLTest.NoBase1
[       OK ] URLTest.NoBase1 (0 ms)
[ RUN      ] URLTest.Base1
[       OK ] URLTest.Base1 (0 ms)
[ RUN      ] URLTest.Base2
[       OK ] URLTest.Base2 (0 ms)
[ RUN      ] URLTest.Base3
[       OK ] URLTest.Base3 (0 ms)
[ RUN      ] URLTest.ToFilePath
[       OK ] URLTest.ToFilePath (0 ms)
[----------] 7 tests from URLTest (1 ms total)

[----------] 20 tests from InspectorSocketTest
[ RUN      ] InspectorSocketTest.ReadsAndWritesInspectorMessage
[       OK ] InspectorSocketTest.ReadsAndWritesInspectorMessage (0 ms)
[ RUN      ] InspectorSocketTest.BufferEdgeCases
[       OK ] InspectorSocketTest.BufferEdgeCases (1 ms)
[ RUN      ] InspectorSocketTest.AcceptsRequestInSeveralWrites
[       OK ] InspectorSocketTest.AcceptsRequestInSeveralWrites (0 ms)
[ RUN      ] InspectorSocketTest.ExtraTextBeforeRequest
[       OK ] InspectorSocketTest.ExtraTextBeforeRequest (0 ms)
[ RUN      ] InspectorSocketTest.RequestWithoutKey
[       OK ] InspectorSocketTest.RequestWithoutKey (1 ms)
[ RUN      ] InspectorSocketTest.KillsConnectionOnProtocolViolation
[       OK ] InspectorSocketTest.KillsConnectionOnProtocolViolation (0 ms)
[ RUN      ] InspectorSocketTest.CanStopReadingFromInspector
[       OK ] InspectorSocketTest.CanStopReadingFromInspector (0 ms)
[ RUN      ] InspectorSocketTest.CloseDoesNotNotifyReadCallback
[       OK ] InspectorSocketTest.CloseDoesNotNotifyReadCallback (1 ms)
[ RUN      ] InspectorSocketTest.CloseWorksWithoutReadEnabled
[       OK ] InspectorSocketTest.CloseWorksWithoutReadEnabled (0 ms)
[ RUN      ] InspectorSocketTest.ReportsHttpGet
[       OK ] InspectorSocketTest.ReportsHttpGet (11 ms)
[ RUN      ] InspectorSocketTest.HandshakeCanBeCanceled
[       OK ] InspectorSocketTest.HandshakeCanBeCanceled (0 ms)
[ RUN      ] InspectorSocketTest.GetThenHandshake
[       OK ] InspectorSocketTest.GetThenHandshake (1 ms)
[ RUN      ] InspectorSocketTest.WriteBeforeHandshake
[       OK ] InspectorSocketTest.WriteBeforeHandshake (0 ms)
[ RUN      ] InspectorSocketTest.CleanupSocketAfterEOF
[       OK ] InspectorSocketTest.CleanupSocketAfterEOF (10 ms)
[ RUN      ] InspectorSocketTest.EOFBeforeHandshake
[       OK ] InspectorSocketTest.EOFBeforeHandshake (0 ms)
[ RUN      ] InspectorSocketTest.Send1Mb
[       OK ] InspectorSocketTest.Send1Mb (25 ms)
[ RUN      ] InspectorSocketTest.ErrorCleansUpTheSocket
[       OK ] InspectorSocketTest.ErrorCleansUpTheSocket (0 ms)
[ RUN      ] InspectorSocketTest.NoCloseResponseFromClient
[       OK ] InspectorSocketTest.NoCloseResponseFromClient (0 ms)
[ RUN      ] InspectorSocketTest.HostCheckedForGET
[       OK ] InspectorSocketTest.HostCheckedForGET (1 ms)
[ RUN      ] InspectorSocketTest.HostCheckedForUPGRADE
[       OK ] InspectorSocketTest.HostCheckedForUPGRADE (0 ms)
[----------] 20 tests from InspectorSocketTest (51 ms total)

[----------] 10 tests from InspectorSocketServerTest
[ RUN      ] InspectorSocketServerTest.InspectorSessions
[       OK ] InspectorSocketServerTest.InspectorSessions (2 ms)
[ RUN      ] InspectorSocketServerTest.ServerDoesNothing
[       OK ] InspectorSocketServerTest.ServerDoesNothing (0 ms)
[ RUN      ] InspectorSocketServerTest.ServerWithoutTargets
[       OK ] InspectorSocketServerTest.ServerWithoutTargets (0 ms)
[ RUN      ] InspectorSocketServerTest.ServerCannotStart
[       OK ] InspectorSocketServerTest.ServerCannotStart (0 ms)
[ RUN      ] InspectorSocketServerTest.StoppingServerDoesNotKillConnections
[       OK ] InspectorSocketServerTest.StoppingServerDoesNotKillConnections (1 ms)
[ RUN      ] InspectorSocketServerTest.ClosingConnectionReportsDone
[       OK ] InspectorSocketServerTest.ClosingConnectionReportsDone (0 ms)
[ RUN      ] InspectorSocketServerTest.ClosingSocketReportsDone
[       OK ] InspectorSocketServerTest.ClosingSocketReportsDone (0 ms)
[ RUN      ] InspectorSocketServerTest.TerminatingSessionReportsDone
[       OK ] InspectorSocketServerTest.TerminatingSessionReportsDone (1 ms)
[ RUN      ] InspectorSocketServerTest.FailsToBindToNodejsHost
[       OK ] InspectorSocketServerTest.FailsToBindToNodejsHost (40 ms)
[ RUN      ] InspectorSocketServerTest.BindsToIpV6
[       OK ] InspectorSocketServerTest.BindsToIpV6 (0 ms)
[----------] 10 tests from InspectorSocketServerTest (44 ms total)

[----------] Global test environment tear-down
[==========] 74 tests from 9 test cases ran. (308 ms total)
[  PASSED  ] 74 tests.
/Applications/Xcode.app/Contents/Developer/usr/bin/make jstest
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C out BUILDTYPE=Release V=1
  touch 14bc63f62e96cfbc513dcfa609a1cd109c24d103.intermediate
  LD_LIBRARY_PATH=/Users/spoon/sfp/node/out/Release/lib.host:/Users/spoon/sfp/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /Users/spoon/sfp/node/out/Release/obj/gen/src/node/inspector/protocol; python deps/v8/third_party/inspector_protocol/CodeGenerator.py --jinja_dir deps/v8/third_party/inspector_protocol/.. --output_base "/Users/spoon/sfp/node/out/Release/obj/gen/src/" --config "/Users/spoon/sfp/node/out/Release/obj/gen/node_protocol_config.json"
  touch 3bc6331644efa748b7c8a3f9d879d754c4289033.intermediate
  LD_LIBRARY_PATH=/Users/spoon/sfp/node/out/Release/lib.host:/Users/spoon/sfp/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../deps/v8/gypfiles; mkdir -p /Users/spoon/sfp/node/out/Release/obj/gen/src/inspector/protocol /Users/spoon/sfp/node/out/Release/obj/gen/include/inspector; python ../third_party/inspector_protocol/CodeGenerator.py --jinja_dir ../third_party --output_base "/Users/spoon/sfp/node/out/Release/obj/gen/src/inspector" --config ../src/inspector/inspector_protocol_config.json
rm 14bc63f62e96cfbc513dcfa609a1cd109c24d103.intermediate 3bc6331644efa748b7c8a3f9d879d754c4289033.intermediate
if [ ! -r node -o ! -L node ]; then ln -fs out/Release/node node; fi
/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python tools/test.py -J --mode=release \
		default \
		addons addons-napi
[03:09|% 100|+ 2269|-   0]: Done 

If wild card dns check (both CN, or SAN) does not
contain port, it applies to all ports on the server.
@nodejs-github-bot nodejs-github-bot added the tls Issues and PRs related to the tls subsystem. label May 22, 2018
Copy link
Member

@bnoordhuis bnoordhuis left a comment

Choose a reason for hiding this comment

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

This doesn't look correct to me. What prompted you to open this pull request?

If you have a certificate with a port number in the CN or DNS SAN, you should get in touch with your registrar for a reissue.

@shiup
Copy link
Author

shiup commented May 22, 2018

@bnoordhuis Ben, it is the other way around..

TLS client: https://really.whatever.com:2443 -----> TLS Server (Server has CN or SAN as *.whatever.com)

The way TLS handle the wild card check (openssl for an example) is : if CN/SAN does not contain port info, it applies to all ports on that server.

Currently node check is missing the above. And when certificate is issued for server, it typically will not contain port for the CN or SAN entry.

Without the above (or something similar) check, the tlsServerCheck is broken for * subjectName check if port is used by the tlsClient. The additional testcases I added will demo the issue.

@apapirovski
Copy link
Member

I could be missing something but checkServerIdentity accepts a hostname which would not include a port number.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski: the proposed change will not modify that - (see the original testcases)

Use the same example above, each protocol has it default port (unless admin changes it.. https: 443, ldaps : 636, and so on)

TLS client: https://really.whatever.com -----> TLS Server (Server has CN or SAN as *.whatever.com)

^^^ this will be over port 443 (automatically without caller/tls client has to do anything). Node current handles this without the above changes. The current* card check is perfect as long as the protocol is using its default port.

The current checkServerIdentity does accept a hostname with a port (if the tls client sends in a port) - this is how I found out the issue..

@apapirovski
Copy link
Member

apapirovski commented May 22, 2018

@shiup if we're passing in host instead of hostname somewhere then that needs to be fixed. The function is fine as it is. It accepts hostname which would never have a port number.

The test cases you've provided are incorrect since they pass in a host (includes port), not a hostname (doesn't include port).

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski that would work.

I am curious on why it would be the prefer fix, as there is a path to the checkServerIdentity, which will pass in hostname:port. Fixing each callers to the that function seems to allow future potential accidentally failures.

It seems like the bullet proof way is closer to the source. (which this proposed fix is)

Just curious, and for my learning.

Question : who will be doing that ? Do you want me to create another PR for path fixing (which I can, but I am more in security than others)

And I think fixing the path will break the 1 % of the case, when the TLS server SAN (highly double CN will) contains a port.

@apapirovski
Copy link
Member

@shiup I'm still unsure where we make the mistake of passing the wrong value. Could you link it? Unfortunately most of the places that refer to host in this code path really mean hostname.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski : will the included test cases provide a clue on where the path needs a kick ?

And I would still partition for doing the check directly in the checkServerIdentity, as there is that 1 % in which the TLS server certificate will contain a port in its hostname. In that scenario, fixing the path will actually breaks it. A couple of the included newly added testcase will demo this.

@apapirovski
Copy link
Member

apapirovski commented May 22, 2018

@shiup No, because your newly added tests have a host value (which by definition includes a port, unlike hostname) being passed directly to checkServerIdentity which is documented as accepting hostname. That is user error.

I see one call site in Node.js itself and it passes in hostname.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski hmm.. checkServerIdentity will have an issue when the TLS server certificate CN/SAN contains a port, will it ? Which unfortunately is also allowed by the spec (let me look up the spec on SAN, it has been a while.. CN is not possible, not sure about the asn1 for SAN).

@apapirovski
Copy link
Member

@shiup I see no evidence that's a valid practice.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski I refreshed my memory with the asn1 spec for x509.. : is not defined as allowed character.. With that in mind, port is not allowed. I can remove some of the testcase.

I withdrawn my concern.

So your preference, fix the path, or the function.

@apapirovski
Copy link
Member

apapirovski commented May 22, 2018

@shiup I guess I still don't get where this is broken. Can you explain? I went to the only call site in the code and it passes in the expected value.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apaprocki: one of the paths (in the node library), not sure where yet - that I need to dig up, is pass in the host, not hostname.

And now that you explain how the host vs hostname is separated in node library, let me also look into the code to make sure we did not use the wrong variable for it..

Thanks ^

@apapirovski
Copy link
Member

apapirovski commented May 22, 2018

@shiup I would have a look at your code. You might be passing in actual host to one of our host options which are meant to accept hostname. (Yes, they're confusingly named... and we're kinda stuck with it at this point.) This is the value that gets passed in FWIW:

  const hostname = options.servername ||
                   options.host ||
                   (options.socket && options.socket._host) ||
                   'localhost';

You can always specify servername.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski thanks for the offering.. Much appreciated.. And thanks for the above host vs hostname. It is very helpful.

We may not have an option, as we use other libraries. The caller I have is just curl with https://seriously.whatever.com:2443 ..

@apapirovski
Copy link
Member

@shiup can you link the third party library? Would love to check it.

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski will do.. (assuming it is not my fault first :-) <-- which is a possibility with host vs hostname. ) Thanks again ^

@shiup
Copy link
Author

shiup commented May 22, 2018

@apapirovski Here is what I found..

Using curl library, passed in https://awesome.whatever.com:6666/testing?seriously. In which it uses this module, https://github.com/request/request. And request.js is setting up the host vs hostname - which is likely wrong based on your explanation above. Does it look reasonable to you ?

Here is my proposed fix..

diff --git a/request.js b/request.js
index 668d9a8..65ca5a1 100644
--- a/request.js
+++ b/request.js
@@ -302,10 +302,10 @@ Request.prototype.init = function (options) {
 
   if (self.proxy && !self.tunnel) {
     self.port = self.proxy.port
-    self.host = self.proxy.hostname
+    self.hostname = self.proxy.hostname
   } else {
     self.port = self.uri.port
-    self.host = self.uri.hostname
+    self.hostname = self.uri.hostname
   }
 
   if (options.form) {

@shiup
Copy link
Author

shiup commented May 23, 2018

This can be closed from the above information.. thanks.

@shiup shiup closed this May 23, 2018
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.

4 participants