diff --git a/Makefile b/Makefile index 70cd0b3e70a..cae2a23a361 100644 --- a/Makefile +++ b/Makefile @@ -22,11 +22,11 @@ endif # to check for changes. .PHONY: node node_g -node: config.gypi +node: config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=Release V=$(V) ln -fs out/Release/node node -node_g: config.gypi +node_g: config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=Debug V=$(V) ln -fs out/Debug/node node_g diff --git a/README.md b/README.md index 309d539b10b..988305facd9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,13 @@ Evented I/O for V8 javascript. [![Build Status](https://secure.travis-ci.org/joy ### To build: -Unix/Macintosh. Requires python 2.6 or 2.7 and GNU make 3.81 or newer: +Prerequisites (Unix only): + + * Python 2.6 or 2.7 + * GNU Make 3.81 or newer + * libexecinfo (FreeBSD and OpenBSD only) + +Unix/Macintosh: ./configure make diff --git a/doc/api/cluster.markdown b/doc/api/cluster.markdown index fa96d488d6b..aa59acbf48a 100644 --- a/doc/api/cluster.markdown +++ b/doc/api/cluster.markdown @@ -357,7 +357,7 @@ the worker finally die. Because there might be long living connections, it is useful to implement a timeout. This example ask the worker to disconnect and after 2 seconds it will destroy the -server. An alternative wound be to execute `worker.destroy()` after 2 seconds, but +server. An alternative would be to execute `worker.destroy()` after 2 seconds, but that would normally not allow the worker to do any cleanup if needed. if (cluster.isMaster) { diff --git a/doc/api/http.markdown b/doc/api/http.markdown index df4976115c3..48c9abaa099 100644 --- a/doc/api/http.markdown +++ b/doc/api/http.markdown @@ -354,7 +354,7 @@ which has been transmitted are equal or not. ### response.statusCode When using implicit headers (not calling `response.writeHead()` explicitly), this property -controls the status code that will be send to the client when the headers get +controls the status code that will be sent to the client when the headers get flushed. Example: @@ -452,7 +452,7 @@ emit trailers, with a list of the header fields in its value. E.g., ### response.end([data], [encoding]) This method signals to the server that all of the response headers and body -has been sent; that server should consider this message complete. +have been sent; that server should consider this message complete. The method, `response.end()`, MUST be called on each response. diff --git a/doc/blog/release/v0.9.1.md b/doc/blog/release/v0.9.1.md new file mode 100644 index 00000000000..dcc0bb0a731 --- /dev/null +++ b/doc/blog/release/v0.9.1.md @@ -0,0 +1,116 @@ +version: 0.9.1 +title: Version 0.9.1 (Unstable) +category: release +slug: node-v0-9-1-unstable +date: 2012-08-28T22:33:45.659Z + +2012.08.28, Version 0.9.1 (Unstable) + +* buffer: Add Buffer.isEncoding(enc) to test for valid encoding values (isaacs) + +* Raise UV_ECANCELED on premature close. (Ben Noordhuis) + +* Remove c-ares from libuv, move to a top-level node dependency (Bert Belder) + +* ref/unref for all HandleWraps, timers, servers, and sockets (Timothy J Fontaine) + +* addon: remove node-waf, superseded by node-gyp (Ben Noordhuis) + +* child_process: emit error on exec failure (Ben Noordhuis) + +* cluster: do not use internal server API (Andreas Madsen) + +* constants: add O_DIRECT (Ian Babrou) + +* crypto: add sync interface to crypto.pbkdf2() (Ben Noordhuis) + +* darwin: emulate fdatasync() (Fedor Indutny) + +* dgram: make .bind() always asynchronous (Ben Noordhuis) + +* events: Make emitter.listeners() side-effect free (isaacs, Joe Andaverde) + +* fs: Throw early on invalid encoding args (isaacs) + +* fs: fix naming of truncate/ftruncate functions (isaacs) + +* http: bubble up parser errors to ClientRequest (Brian White) + +* linux: improve cpuinfo parser on ARM and MIPS (Ben Noordhuis) + +* net: add support for IPv6 addresses ending in :: (Josh Erickson) + +* net: support Server.listen(Pipe) (Andreas Madsen) + +* node: don't scan add-on for "init" symbol (Ben Noordhuis) + +* remove process.uvCounters() (Ben Noordhuis) + +* repl: console writes to repl rather than process stdio (Nathan Rajlich) + +* timers: implement setImmediate (Timothy J Fontaine) + +* tls: fix segfault in pummel/test-tls-ci-reneg-attack (Ben Noordhuis) + +* tools: Move gyp addon tools to node-gyp (Nathan Rajlich) + +* unix: preliminary signal handler support (Ben Noordhuis) + +* unix: remove dependency on ev_child (Ben Noordhuis) + +* unix: work around darwin bug, don't poll() on pipe (Fedor Indutny) + +* util: Formally deprecate util.pump() (Ben Noordhuis) + +* windows: make active and closing handle state independent (Bert Belder) + +* windows: report spawn errors to the exit callback (Bert Belder) + +* windows: signal handling support with uv_signal_t (Bert Belder) + + +Source Code: http://nodejs.org/dist/v0.9.1/node-v0.9.1.tar.gz + +Macintosh Installer (Universal): http://nodejs.org/dist/v0.9.1/node-v0.9.1.pkg + +Windows Installer: http://nodejs.org/dist/v0.9.1/node-v0.9.1-x86.msi + +Windows x64 Installer: http://nodejs.org/dist/v0.9.1/x64/node-v0.9.1-x64.msi + +Windows x64 Files: http://nodejs.org/dist/v0.9.1/x64/ + +Linux 32-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-linux-x86.tar.gz + +Linux 64-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-linux-x64.tar.gz + +Solaris 32-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-sunos-x86.tar.gz + +Solaris 64-bit Binary: http://nodejs.org/dist/v0.9.1/node-v0.9.1-sunos-x64.tar.gz + +Other release files: http://nodejs.org/dist/v0.9.1/ + +Website: http://nodejs.org/docs/v0.9.1/ + +Documentation: http://nodejs.org/docs/v0.9.1/api/ + +Shasums: + +``` +b86a5b0b2c9a89d08baaeb3d5270a8f247b4ba43 node-v0.9.1-darwin-x64.tar.gz +800af9d15a4b65e624351bb94dedc3b7eb322b86 node-v0.9.1-darwin-x86.tar.gz +a7ea43b0db472ca84dc9838960dae57ff0abaa72 node-v0.9.1-linux-x64.tar.gz +89c4be492a946eefa45aa87d16787875aa0f2dff node-v0.9.1-linux-x86.tar.gz +6495d2814541e945dba5941b8d3facf2a61dc55d node-v0.9.1-sunos-x64.tar.gz +05ea83ba4d648f5b949833bb28d69e6eeebabb78 node-v0.9.1-sunos-x86.tar.gz +3ccf1ac2fea7f2d05bcaed590bc54ee61c982fbb node-v0.9.1-x86.msi +bd0ede40e4681b16088284fe6a18ae3a5c5a3795 node-v0.9.1.tar.gz +159470a999ef23fa940ad3c54265053c3d2a4332 node.exe +02472e388a44b91e2644178a0fe011354fcd361e node.exp +c6d6ce22be4b47ad022d82dd91ebd4c040742fee node.lib +7b4cec8b4106d90a077388fe483fdbb13119dcb1 node.pdb +a5fbf5e22c7623a9206abc6608d084ff53c7c4c9 x64/node-v0.9.1-x64.msi +9755685a9d7bea6dc63d3260829c26c5b0430a7a x64/node.exe +621f177733647848f7f667926fe4f498a1f50c97 x64/node.exp +5877dffbf012c458dab88f3392af59cb33720d2f x64/node.lib +dc513ce5c16771dcfab9c1777d5949252290b412 x64/node.pdb +``` diff --git a/lib/child_process.js b/lib/child_process.js index d6f62cb7c7f..e1af90fb483 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -300,6 +300,9 @@ function setupChannel(target, channel) { } else { this.buffering = false; target.disconnect(); + channel.onread = nop; + channel.close(); + maybeClose(target); } }; @@ -755,7 +758,7 @@ ChildProcess.prototype.spawn = function(options) { ipc = createPipe(true); ipcFd = i; - acc.push({ type: 'pipe', handle: ipc }); + acc.push({ type: 'pipe', handle: ipc, ipc: true }); } else if (typeof stdio === 'number' || typeof stdio.fd === 'number') { acc.push({ type: 'fd', fd: stdio.fd || stdio }); } else if (getHandleWrapType(stdio) || getHandleWrapType(stdio.handle) || @@ -806,6 +809,11 @@ ChildProcess.prototype.spawn = function(options) { stdio.forEach(function(stdio, i) { if (stdio.type === 'ignore') return; + if (stdio.ipc) { + self._closesNeeded++; + return; + } + if (stdio.handle) { // when i === 0 - we're dealing with stdin // (which is the only one writable pipe) diff --git a/lib/net.js b/lib/net.js index 8108f160cb3..0decfe963c8 100644 --- a/lib/net.js +++ b/lib/net.js @@ -106,6 +106,7 @@ function normalizeConnectArgs(args) { var cb = args[args.length - 1]; return (typeof cb === 'function') ? [options, cb] : [options]; } +exports._normalizeConnectArgs = normalizeConnectArgs; /* called when creating new Socket, or when re-using a closed Socket */ diff --git a/lib/tls.js b/lib/tls.js index a104bdf7386..8c505998870 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -1217,34 +1217,24 @@ Server.prototype.SNICallback = function(servername) { // }); // // +function normalizeConnectArgs(listArgs) { + var args = net._normalizeConnectArgs(listArgs); + var options = args[0]; + var cb = args[1]; + + if (typeof listArgs[1] === 'object') { + options = util._extend(options, listArgs[1]); + } else if (typeof listArgs[2] === 'object') { + options = util._extend(options, listArgs[2]); + } + + return (cb) ? [options, cb] : [options]; +} + exports.connect = function(/* [port, host], options, cb */) { - var options, port, host, cb; - - if (typeof arguments[0] === 'object') { - options = arguments[0]; - } else if (typeof arguments[1] === 'object') { - options = arguments[1]; - port = arguments[0]; - } else if (typeof arguments[2] === 'object') { - options = arguments[2]; - port = arguments[0]; - host = arguments[1]; - } else { - // This is what happens when user passes no `options` argument, we can't - // throw `TypeError` here because it would be incompatible with old API - if (typeof arguments[0] === 'number') { - port = arguments[0]; - } - if (typeof arguments[1] === 'string') { - host = arguments[1]; - } - } - - options = util._extend({ port: port, host: host }, options || {}); - - if (typeof arguments[arguments.length - 1] === 'function') { - cb = arguments[arguments.length - 1]; - } + var args = normalizeConnectArgs(arguments); + var options = args[0]; + var cb = args[1]; var socket = options.socket ? options.socket : new net.Stream(); @@ -1269,11 +1259,12 @@ exports.connect = function(/* [port, host], options, cb */) { } if (!options.socket) { - socket.connect({ + var connect_opt = (options.path && !options.port) ? {path: options.path} : { port: options.port, host: options.host, localAddress: options.localAddress - }); + }; + socket.connect(connect_opt); } pair.on('secure', function() { diff --git a/src/node.js b/src/node.js index af6ab34dcb6..115441eb6a0 100644 --- a/src/node.js +++ b/src/node.js @@ -560,6 +560,10 @@ }; startup.processSignalHandlers = function() { + // Not supported on Windows. + if (process.platform === 'win32') + return; + // Load events module in order to access prototype elements on process like // process.addListener. var signalWraps = {}; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 5b2029c32aa..b3e34b36565 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -942,23 +942,20 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) { } p->servername_ = Persistent::New(String::New(servername)); - // Call sniCallback_ and use it's return value as context - if (!p->sniCallback_.IsEmpty()) { + // Call the SNI callback and use its return value as context + if (!p->sniObject_.IsEmpty()) { if (!p->sniContext_.IsEmpty()) { p->sniContext_.Dispose(); } // Get callback init args Local argv[1] = {*p->servername_}; - Local callback = *p->sniCallback_; // Call it - // - // XXX There should be an object connected to this that - // we can attach a domain onto. - Local ret; - ret = Local::New(MakeCallback(Context::GetCurrent()->Global(), - callback, ARRAY_SIZE(argv), argv)); + Local ret = Local::New(MakeCallback(p->sniObject_, + "onselect", + ARRAY_SIZE(argv), + argv)); // If ret is SecureContext if (secure_context_constructor->HasInstance(ret)) { @@ -1778,11 +1775,11 @@ Handle Connection::SetSNICallback(const Arguments& args) { } // Release old handle - if (!ss->sniCallback_.IsEmpty()) { - ss->sniCallback_.Dispose(); + if (!ss->sniObject_.IsEmpty()) { + ss->sniObject_.Dispose(); } - ss->sniCallback_ = Persistent::New( - Local::Cast(args[0])); + ss->sniObject_ = Persistent::New(Object::New()); + ss->sniObject_->Set(String::New("onselect"), args[0]); return True(); } @@ -4207,7 +4204,7 @@ struct pbkdf2_req { size_t iter; char* key; size_t keylen; - Persistent callback; + Persistent obj; }; @@ -4253,13 +4250,10 @@ void EIO_PBKDF2After(uv_work_t* work_req) { HandleScope scope; Local argv[2]; - Persistent cb = req->callback; + Persistent obj = req->obj; EIO_PBKDF2After(req, argv); - - // XXX There should be an object connected to this that - // we can attach a domain onto. - MakeCallback(Context::GetCurrent()->Global(), cb, ARRAY_SIZE(argv), argv); - cb.Dispose(); + MakeCallback(obj, "ondone", ARRAY_SIZE(argv), argv); + obj.Dispose(); } @@ -4275,7 +4269,6 @@ Handle PBKDF2(const Arguments& args) { ssize_t pass_written = -1; ssize_t salt_written = -1; ssize_t iter = -1; - Local callback; pbkdf2_req* req = NULL; if (args.Length() != 4 && args.Length() != 5) { @@ -4338,8 +4331,8 @@ Handle PBKDF2(const Arguments& args) { req->keylen = keylen; if (args[4]->IsFunction()) { - callback = Local::Cast(args[4]); - req->callback = Persistent::New(callback); + req->obj = Persistent::New(Object::New()); + req->obj->Set(String::New("ondone"), args[4]); uv_queue_work(uv_default_loop(), &req->work_req, EIO_PBKDF2, @@ -4364,7 +4357,7 @@ typedef int (*RandomBytesGenerator)(unsigned char* buf, int size); struct RandomBytesRequest { ~RandomBytesRequest(); - Persistent callback_; + Persistent obj_; unsigned long error_; // openssl error code or zero uv_work_t work_req_; size_t size_; @@ -4373,10 +4366,9 @@ struct RandomBytesRequest { RandomBytesRequest::~RandomBytesRequest() { - if (!callback_.IsEmpty()) { - callback_.Dispose(); - callback_.Clear(); - } + if (obj_.IsEmpty()) return; + obj_.Dispose(); + obj_.Clear(); } @@ -4437,12 +4429,7 @@ void RandomBytesAfter(uv_work_t* work_req) { HandleScope scope; Local argv[2]; RandomBytesCheck(req, argv); - - // XXX There should be an object connected to this that - // we can attach a domain onto. - MakeCallback(Context::GetCurrent()->Global(), - req->callback_, - ARRAY_SIZE(argv), argv); + MakeCallback(req->obj_, "ondone", ARRAY_SIZE(argv), argv); delete req; } @@ -4467,15 +4454,15 @@ Handle RandomBytes(const Arguments& args) { req->size_ = size; if (args[1]->IsFunction()) { - Local callback_v = Local(Function::Cast(*args[1])); - req->callback_ = Persistent::New(callback_v); + req->obj_ = Persistent::New(Object::New()); + req->obj_->Set(String::New("ondone"), args[1]); uv_queue_work(uv_default_loop(), &req->work_req_, RandomBytesWork, RandomBytesAfter); - return Undefined(); + return req->obj_; } else { Local argv[2]; diff --git a/src/node_crypto.h b/src/node_crypto.h index 1ee23c8a74b..fe433596ac4 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -110,7 +110,7 @@ class Connection : ObjectWrap { #endif #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - v8::Persistent sniCallback_; + v8::Persistent sniObject_; v8::Persistent sniContext_; v8::Persistent servername_; #endif @@ -185,7 +185,7 @@ class Connection : ObjectWrap { #endif #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB - if (!sniCallback_.IsEmpty()) sniCallback_.Dispose(); + if (!sniObject_.IsEmpty()) sniObject_.Dispose(); if (!sniContext_.IsEmpty()) sniContext_.Dispose(); if (!servername_.IsEmpty()) servername_.Dispose(); #endif diff --git a/test/fixtures/child-process-message-and-exit.js b/test/fixtures/child-process-message-and-exit.js new file mode 100644 index 00000000000..56e83ce801a --- /dev/null +++ b/test/fixtures/child-process-message-and-exit.js @@ -0,0 +1,3 @@ + +process.send('hello'); +process.exit(0); diff --git a/test/pummel/test-https-ci-reneg-attack.js b/test/pummel/test-https-ci-reneg-attack.js new file mode 100644 index 00000000000..83b76b45850 --- /dev/null +++ b/test/pummel/test-https-ci-reneg-attack.js @@ -0,0 +1,106 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var spawn = require('child_process').spawn; +var tls = require('tls'); +var https = require('https'); +var fs = require('fs'); + +// renegotiation limits to test +var LIMITS = [0, 1, 2, 3, 5, 10, 16]; + +if (process.platform === 'win32') { + console.log('Skipping test, you probably don\'t have openssl installed.'); + process.exit(); +} + +(function() { + var n = 0; + function next() { + if (n >= LIMITS.length) return; + tls.CLIENT_RENEG_LIMIT = LIMITS[n++]; + test(next); + } + next(); +})(); + +function test(next) { + var options = { + cert: fs.readFileSync(common.fixturesDir + '/test_cert.pem'), + key: fs.readFileSync(common.fixturesDir + '/test_key.pem') + }; + + var seenError = false; + + var server = https.createServer(options, function(req, res) { + var conn = req.connection; + conn.on('error', function(err) { + console.error('Caught exception: ' + err); + assert(/TLS session renegotiation attack/.test(err)); + conn.destroy(); + seenError = true; + }); + res.end('ok'); + }); + + server.listen(common.PORT, function() { + var args = ('s_client -connect 127.0.0.1:' + common.PORT).split(' '); + var child = spawn('openssl', args); + + child.stdout.pipe(process.stdout); + child.stderr.pipe(process.stderr); + + // count handshakes, start the attack after the initial handshake is done + var handshakes = 0; + var renegs = 0; + + child.stderr.on('data', function(data) { + if (seenError) return; + handshakes += (('' + data).match(/verify return:1/g) || []).length; + if (handshakes === 2) spam(); + renegs += (('' + data).match(/RENEGOTIATING/g) || []).length; + }); + + child.on('exit', function() { + assert.equal(renegs, tls.CLIENT_RENEG_LIMIT + 1); + server.close(); + process.nextTick(next); + }); + + var closed = false; + child.stdin.on('error', function(err) { + assert.equal(err.code, 'EPIPE'); + closed = true; + }); + child.stdin.on('close', function() { + closed = true; + }); + + // simulate renegotiation attack + function spam() { + if (closed) return; + child.stdin.write('R\n'); + setTimeout(spam, 50); + } + }); +} diff --git a/test/simple/test-child-process-fork-close.js b/test/simple/test-child-process-fork-close.js new file mode 100644 index 00000000000..342cffec3c3 --- /dev/null +++ b/test/simple/test-child-process-fork-close.js @@ -0,0 +1,57 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var assert = require('assert'), + common = require('../common'), + fork = require('child_process').fork, + fork = require('child_process').fork; + +var cp = fork(common.fixturesDir + '/child-process-message-and-exit.js'); + +var gotMessage = false, + gotExit = false, + gotClose = false; + +cp.on('message', function(message) { + assert(!gotMessage); + assert(!gotClose); + assert.strictEqual(message, 'hello'); + gotMessage = true; +}); + +cp.on('exit', function() { + assert(!gotExit); + assert(!gotClose); + gotExit = true; +}); + +cp.on('close', function() { + assert(gotMessage); + assert(gotExit); + assert(!gotClose); + gotClose = true; +}); + +process.on('exit', function() { + assert(gotMessage); + assert(gotExit); + assert(gotClose); +}); diff --git a/test/simple/test-domain-crypto.js b/test/simple/test-domain-crypto.js new file mode 100644 index 00000000000..66e96288044 --- /dev/null +++ b/test/simple/test-domain-crypto.js @@ -0,0 +1,37 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +try { + var crypto = require('crypto'); +} catch (e) { + console.log('Not compiled with OPENSSL support.'); + process.exit(); +} + +// the missing var keyword is intentional +domain = require('domain'); + +// should not throw a 'TypeError: undefined is not a function' exception +crypto.randomBytes(8); +crypto.randomBytes(8, function() {}); +crypto.pseudoRandomBytes(8); +crypto.pseudoRandomBytes(8, function() {}); +crypto.pbkdf2('password', 'salt', 8, 8, function() {}); diff --git a/test/simple/test-tls-connect-pipe.js b/test/simple/test-tls-connect-pipe.js new file mode 100644 index 00000000000..f58aaabcfe8 --- /dev/null +++ b/test/simple/test-tls-connect-pipe.js @@ -0,0 +1,49 @@ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var common = require('../common'); +var assert = require('assert'); +var tls = require('tls'); +var fs = require('fs'); + +var clientConnected = 0; +var serverConnected = 0; + +var options = { + key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') +}; + +var server = tls.Server(options, function(socket) { + ++serverConnected; + server.close(); +}); +server.listen(common.PIPE, function() { + var client = tls.connect(common.PIPE, function() { + ++clientConnected; + client.end(); + }); +}); + +process.on('exit', function() { + assert.equal(clientConnected, 1); + assert.equal(serverConnected, 1); +});