Merge remote-tracking branch 'ry/v0.6' into v0.6-merge
Conflicts: AUTHORS ChangeLog Makefile doc/about/index.html doc/api/tls.markdown doc/community/index.html doc/index.html doc/logos/index.html doc/template.html lib/http.js lib/tls.js src/node_version.h src/platform_win32.cc test/simple/test-tls-connect-given-socket.js
This commit is contained in:
commit
31721da4b1
3
AUTHORS
3
AUTHORS
@ -263,3 +263,6 @@ Dan VerWeire <dverweire@gmail.com>
|
|||||||
Matthew Fitzsimmons <matt@joyent.com>
|
Matthew Fitzsimmons <matt@joyent.com>
|
||||||
Philip Tellis <philip.tellis@gmail.com>
|
Philip Tellis <philip.tellis@gmail.com>
|
||||||
Christopher Jeffrey <chjjeffrey@gmail.com>
|
Christopher Jeffrey <chjjeffrey@gmail.com>
|
||||||
|
Paddy Byers <paddy.byers@gmail.com>
|
||||||
|
Seth Fitzsimmons <seth@mojodna.net>
|
||||||
|
Einar Otto Stangvik <einaros@gmail.com>
|
||||||
|
42
ChangeLog
42
ChangeLog
@ -97,7 +97,47 @@
|
|||||||
* Bug fixes
|
* Bug fixes
|
||||||
|
|
||||||
|
|
||||||
2012.02.02, Version 0.6.10 (stable)
|
2012.02.17 Version 0.6.11 (stable), 1eb1fe32250fc88cb5b0a97cddf3e02be02e3f4a
|
||||||
|
|
||||||
|
* http: allow multiple WebSocket RFC6455 headers (Einar Otto Stangvik)
|
||||||
|
|
||||||
|
* http: allow multiple WWW-Authenticate headers (Ben Noordhuis)
|
||||||
|
|
||||||
|
* windows: support unicode argv and environment variables (Bert Belder)
|
||||||
|
|
||||||
|
* tls: mitigate session renegotiation attacks (Ben Noordhuis)
|
||||||
|
|
||||||
|
* tcp, pipe: don't assert on uv_accept() errors (Ben Noordhuis)
|
||||||
|
|
||||||
|
* tls: Allow establishing secure connection on the existing socket (koichik)
|
||||||
|
|
||||||
|
* dgram: handle close of dgram socket before DNS lookup completes (Seth Fitzsimmons)
|
||||||
|
|
||||||
|
* windows: Support half-duplex pipes (Igor Zinkovsky)
|
||||||
|
|
||||||
|
* build: disable omit-frame-pointer on solaris systems (Dave Pacheco)
|
||||||
|
|
||||||
|
* debugger: fix --debug-brk (Ben Noordhuis)
|
||||||
|
|
||||||
|
* net: fix large file downloads failing (koichik)
|
||||||
|
|
||||||
|
* fs: fix ReadStream failure to read from existing fd (Christopher Jeffrey)
|
||||||
|
|
||||||
|
* net: destroy socket on DNS error (Stefan Rusu)
|
||||||
|
|
||||||
|
* dtrace: add missing translator (Dave Pacheco)
|
||||||
|
|
||||||
|
* unix: don't flush tty on switch to raw mode (Ben Noordhuis)
|
||||||
|
|
||||||
|
* windows: reset brightness when reverting to default text color (Bert Belder)
|
||||||
|
|
||||||
|
* npm: update to 1.1.1
|
||||||
|
- Update which, fstream, mkdirp, request, and rimraf
|
||||||
|
- Fix #2123 Set path properly for lifecycle scripts on windows
|
||||||
|
- Mark the root as seen, so we don't recurse into it. Fixes #1838. (Martin Cooper)
|
||||||
|
|
||||||
|
|
||||||
|
2012.02.02, Version 0.6.10 (stable), 051908e023f87894fa68f5b64d0b99a19a7db01e
|
||||||
|
|
||||||
* Update V8 to 3.6.6.20
|
* Update V8 to 3.6.6.20
|
||||||
|
|
||||||
|
4
deps/uv/src/unix/tty.c
vendored
4
deps/uv/src/unix/tty.c
vendored
@ -76,8 +76,8 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) {
|
|||||||
raw.c_cc[VMIN] = 1;
|
raw.c_cc[VMIN] = 1;
|
||||||
raw.c_cc[VTIME] = 0;
|
raw.c_cc[VTIME] = 0;
|
||||||
|
|
||||||
/* Put terminal in raw mode after flushing */
|
/* Put terminal in raw mode after draining */
|
||||||
if (tcsetattr(fd, TCSAFLUSH, &raw)) {
|
if (tcsetattr(fd, TCSADRAIN, &raw)) {
|
||||||
goto fatal;
|
goto fatal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
deps/uv/src/win/error.c
vendored
3
deps/uv/src/win/error.c
vendored
@ -108,6 +108,9 @@ uv_err_code uv_translate_sys_error(int sys_errno) {
|
|||||||
case ERROR_INVALID_PARAMETER: return UV_EINVAL;
|
case ERROR_INVALID_PARAMETER: return UV_EINVAL;
|
||||||
case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET;
|
case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET;
|
||||||
case ERROR_BROKEN_PIPE: return UV_EOF;
|
case ERROR_BROKEN_PIPE: return UV_EOF;
|
||||||
|
case ERROR_BAD_PIPE: return UV_EPIPE;
|
||||||
|
case ERROR_NO_DATA: return UV_EPIPE;
|
||||||
|
case ERROR_PIPE_NOT_CONNECTED: return UV_EPIPE;
|
||||||
case ERROR_PIPE_BUSY: return UV_EBUSY;
|
case ERROR_PIPE_BUSY: return UV_EBUSY;
|
||||||
case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT;
|
case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT;
|
||||||
case WSAETIMEDOUT: return UV_ETIMEDOUT;
|
case WSAETIMEDOUT: return UV_ETIMEDOUT;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<style>
|
<style>
|
||||||
|
@ -26,8 +26,40 @@ Alternatively you can send the CSR to a Certificate Authority for signing.
|
|||||||
(TODO: docs on creating a CA, for now interested users should just look at
|
(TODO: docs on creating a CA, for now interested users should just look at
|
||||||
`test/fixtures/keys/Makefile` in the Node source code)
|
`test/fixtures/keys/Makefile` in the Node source code)
|
||||||
|
|
||||||
|
### Client-initiated renegotiation attack mitigation
|
||||||
|
|
||||||
#### tls.createServer(options, [secureConnectionListener])
|
The TLS protocol lets the client renegotiate certain aspects of the TLS session.
|
||||||
|
Unfortunately, session renegotiation requires a disproportional amount of
|
||||||
|
server-side resources, which makes it a potential vector for denial-of-service
|
||||||
|
attacks.
|
||||||
|
|
||||||
|
To mitigate this, renegotiations are limited to three times every 10 minutes. An
|
||||||
|
error is emitted on the [CleartextStream](#tls.CleartextStream) instance when
|
||||||
|
the threshold is exceeded. The limits are configurable:
|
||||||
|
|
||||||
|
- `tls.CLIENT_RENEG_LIMIT`: renegotiation limit, default is 3.
|
||||||
|
|
||||||
|
- `tls.CLIENT_RENEG_WINDOW`: renegotiation window in seconds, default is
|
||||||
|
10 minutes.
|
||||||
|
|
||||||
|
Don't change the defaults unless you know what you are doing.
|
||||||
|
|
||||||
|
To test your server, connect to it with `openssl s_client -connect address:port`
|
||||||
|
and tap `R<CR>` (that's the letter `R` followed by a carriage return) a few
|
||||||
|
times.
|
||||||
|
|
||||||
|
|
||||||
|
### NPN and SNI
|
||||||
|
|
||||||
|
NPN (Next Protocol Negotiation) and SNI (Server Name Indication) are TLS
|
||||||
|
handshake extensions allowing you:
|
||||||
|
|
||||||
|
* NPN - to use one TLS server for multiple protocols (HTTP, SPDY)
|
||||||
|
* SNI - to use one TLS server for multiple hostnames with different SSL
|
||||||
|
certificates.
|
||||||
|
|
||||||
|
|
||||||
|
## tls.createServer(options, [secureConnectionListener])
|
||||||
|
|
||||||
Creates a new [tls.Server](#tls.Server).
|
Creates a new [tls.Server](#tls.Server).
|
||||||
The `connectionListener` argument is automatically set as a listener for the
|
The `connectionListener` argument is automatically set as a listener for the
|
||||||
@ -144,6 +176,11 @@ Creates a new client connection to the given `port` and `host` (old API) or
|
|||||||
|
|
||||||
- `servername`: Servername for SNI (Server Name Indication) TLS extension.
|
- `servername`: Servername for SNI (Server Name Indication) TLS extension.
|
||||||
|
|
||||||
|
- `socket`: Establish secure connection on a given socket rather than
|
||||||
|
creating a new socket. If this option is specified, `host` and `port`
|
||||||
|
are ignored. This is intended FOR INTERNAL USE ONLY. As with all
|
||||||
|
undocumented APIs in Node, they should not be used.
|
||||||
|
|
||||||
The `secureConnectListener` parameter will be added as a listener for the
|
The `secureConnectListener` parameter will be added as a listener for the
|
||||||
['secureConnect'](#event_secureConnect_) event.
|
['secureConnect'](#event_secureConnect_) event.
|
||||||
|
|
||||||
@ -178,27 +215,7 @@ Here is an example of a client of echo server as described previously:
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
### STARTTLS
|
## tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
|
||||||
|
|
||||||
In the v0.4 branch no function exists for starting a TLS session on an
|
|
||||||
already existing TCP connection. This is possible it just requires a bit of
|
|
||||||
work. The technique is to use `tls.createSecurePair()` which returns two
|
|
||||||
streams: an encrypted stream and a cleartext stream. The encrypted stream is
|
|
||||||
then piped to the socket, the cleartext stream is what the user interacts with
|
|
||||||
thereafter.
|
|
||||||
|
|
||||||
[Here is some code that does it.](http://gist.github.com/848444)
|
|
||||||
|
|
||||||
### NPN and SNI
|
|
||||||
|
|
||||||
NPN (Next Protocol Negotiation) and SNI (Server Name Indication) are TLS
|
|
||||||
handshake extensions allowing you:
|
|
||||||
|
|
||||||
* NPN - to use one TLS server for multiple protocols (HTTP, SPDY)
|
|
||||||
* SNI - to use one TLS server for multiple hostnames with different SSL
|
|
||||||
certificates.
|
|
||||||
|
|
||||||
### pair = tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
|
|
||||||
|
|
||||||
Creates a new secure pair object with two streams, one of which reads/writes
|
Creates a new secure pair object with two streams, one of which reads/writes
|
||||||
encrypted data, and one reads/writes cleartext data.
|
encrypted data, and one reads/writes cleartext data.
|
||||||
@ -220,7 +237,7 @@ and the cleartext one is used as a replacement for the initial encrypted stream.
|
|||||||
`tls.createSecurePair()` returns a SecurePair object with
|
`tls.createSecurePair()` returns a SecurePair object with
|
||||||
[cleartext](#tls.CleartextStream) and `encrypted` stream properties.
|
[cleartext](#tls.CleartextStream) and `encrypted` stream properties.
|
||||||
|
|
||||||
#### Event: 'secure'
|
### Event: 'secure'
|
||||||
|
|
||||||
The event is emitted from the SecurePair once the pair has successfully
|
The event is emitted from the SecurePair once the pair has successfully
|
||||||
established a secure connection.
|
established a secure connection.
|
||||||
@ -229,13 +246,13 @@ Similarly to the checking for the server 'secureConnection' event,
|
|||||||
pair.cleartext.authorized should be checked to confirm whether the certificate
|
pair.cleartext.authorized should be checked to confirm whether the certificate
|
||||||
used properly authorized.
|
used properly authorized.
|
||||||
|
|
||||||
### tls.Server
|
## tls.Server
|
||||||
|
|
||||||
This class is a subclass of `net.Server` and has the same methods on it.
|
This class is a subclass of `net.Server` and has the same methods on it.
|
||||||
Instead of accepting just raw TCP connections, this accepts encrypted
|
Instead of accepting just raw TCP connections, this accepts encrypted
|
||||||
connections using TLS or SSL.
|
connections using TLS or SSL.
|
||||||
|
|
||||||
#### Event: 'secureConnection'
|
### Event: 'secureConnection'
|
||||||
|
|
||||||
`function (cleartextStream) {}`
|
`function (cleartextStream) {}`
|
||||||
|
|
||||||
@ -255,7 +272,7 @@ server, you unauthorized connections may be accepted.
|
|||||||
SNI.
|
SNI.
|
||||||
|
|
||||||
|
|
||||||
#### Event: 'clientError'
|
### Event: 'clientError'
|
||||||
|
|
||||||
`function (exception) { }`
|
`function (exception) { }`
|
||||||
|
|
||||||
@ -263,7 +280,7 @@ When a client connection emits an 'error' event before secure connection is
|
|||||||
established - it will be forwarded here.
|
established - it will be forwarded here.
|
||||||
|
|
||||||
|
|
||||||
#### server.listen(port, [host], [callback])
|
### server.listen(port, [host], [callback])
|
||||||
|
|
||||||
Begin accepting connections on the specified `port` and `host`. If the
|
Begin accepting connections on the specified `port` and `host`. If the
|
||||||
`host` is omitted, the server will accept connections directed to any
|
`host` is omitted, the server will accept connections directed to any
|
||||||
@ -275,35 +292,35 @@ when the server has been bound.
|
|||||||
See `net.Server` for more information.
|
See `net.Server` for more information.
|
||||||
|
|
||||||
|
|
||||||
#### server.close()
|
### server.close()
|
||||||
|
|
||||||
Stops the server from accepting new connections. This function is
|
Stops the server from accepting new connections. This function is
|
||||||
asynchronous, the server is finally closed when the server emits a `'close'`
|
asynchronous, the server is finally closed when the server emits a `'close'`
|
||||||
event.
|
event.
|
||||||
|
|
||||||
#### server.address()
|
### server.address()
|
||||||
|
|
||||||
Returns the bound address and port of the server as reported by the operating
|
Returns the bound address and port of the server as reported by the operating
|
||||||
system.
|
system.
|
||||||
See [net.Server.address()](net.html#server.address) for more information.
|
See [net.Server.address()](net.html#server.address) for more information.
|
||||||
|
|
||||||
#### server.addContext(hostname, credentials)
|
### server.addContext(hostname, credentials)
|
||||||
|
|
||||||
Add secure context that will be used if client request's SNI hostname is
|
Add secure context that will be used if client request's SNI hostname is
|
||||||
matching passed `hostname` (wildcards can be used). `credentials` can contain
|
matching passed `hostname` (wildcards can be used). `credentials` can contain
|
||||||
`key`, `cert` and `ca`.
|
`key`, `cert` and `ca`.
|
||||||
|
|
||||||
#### server.maxConnections
|
### server.maxConnections
|
||||||
|
|
||||||
Set this property to reject connections when the server's connection count
|
Set this property to reject connections when the server's connection count
|
||||||
gets high.
|
gets high.
|
||||||
|
|
||||||
#### server.connections
|
### server.connections
|
||||||
|
|
||||||
The number of concurrent connections on the server.
|
The number of concurrent connections on the server.
|
||||||
|
|
||||||
|
|
||||||
### tls.CleartextStream
|
## tls.CleartextStream
|
||||||
|
|
||||||
This is a stream on top of the *Encrypted* stream that makes it possible to
|
This is a stream on top of the *Encrypted* stream that makes it possible to
|
||||||
read/write an encrypted data as a cleartext data.
|
read/write an encrypted data as a cleartext data.
|
||||||
@ -311,7 +328,7 @@ read/write an encrypted data as a cleartext data.
|
|||||||
This instance implements a duplex [Stream](streams.html#streams) interfaces.
|
This instance implements a duplex [Stream](streams.html#streams) interfaces.
|
||||||
It has all the common stream methods and events.
|
It has all the common stream methods and events.
|
||||||
|
|
||||||
#### Event: 'secureConnect'
|
### Event: 'secureConnect'
|
||||||
|
|
||||||
`function () {}`
|
`function () {}`
|
||||||
|
|
||||||
@ -323,17 +340,17 @@ If `cleartextStream.authorized === false` then the error can be found in
|
|||||||
`cleartextStream.authorizationError`. Also if NPN was used - you can check
|
`cleartextStream.authorizationError`. Also if NPN was used - you can check
|
||||||
`cleartextStream.npnProtocol` for negotiated protocol.
|
`cleartextStream.npnProtocol` for negotiated protocol.
|
||||||
|
|
||||||
#### cleartextStream.authorized
|
### cleartextStream.authorized
|
||||||
|
|
||||||
A boolean that is `true` if the peer certificate was signed by one of the
|
A boolean that is `true` if the peer certificate was signed by one of the
|
||||||
specified CAs, otherwise `false`
|
specified CAs, otherwise `false`
|
||||||
|
|
||||||
#### cleartextStream.authorizationError
|
### cleartextStream.authorizationError
|
||||||
|
|
||||||
The reason why the peer's certificate has not been verified. This property
|
The reason why the peer's certificate has not been verified. This property
|
||||||
becomes available only when `cleartextStream.authorized === false`.
|
becomes available only when `cleartextStream.authorized === false`.
|
||||||
|
|
||||||
#### cleartextStream.getPeerCertificate()
|
### cleartextStream.getPeerCertificate()
|
||||||
|
|
||||||
Returns an object representing the peer's certificate. The returned object has
|
Returns an object representing the peer's certificate. The returned object has
|
||||||
some properties corresponding to the field of the certificate.
|
some properties corresponding to the field of the certificate.
|
||||||
@ -361,17 +378,17 @@ Example:
|
|||||||
If the peer does not provide a certificate, it returns `null` or an empty
|
If the peer does not provide a certificate, it returns `null` or an empty
|
||||||
object.
|
object.
|
||||||
|
|
||||||
#### cleartextStream.address()
|
### cleartextStream.address()
|
||||||
|
|
||||||
Returns the bound address and port of the underlying socket as reported by the
|
Returns the bound address and port of the underlying socket as reported by the
|
||||||
operating system. Returns an object with two properties, e.g.
|
operating system. Returns an object with two properties, e.g.
|
||||||
`{"address":"192.168.57.1", "port":62053}`
|
`{"address":"192.168.57.1", "port":62053}`
|
||||||
|
|
||||||
#### cleartextStream.remoteAddress
|
### cleartextStream.remoteAddress
|
||||||
|
|
||||||
The string representation of the remote IP address. For example,
|
The string representation of the remote IP address. For example,
|
||||||
`'74.125.127.100'` or `'2001:4860:a005::68'`.
|
`'74.125.127.100'` or `'2001:4860:a005::68'`.
|
||||||
|
|
||||||
#### cleartextStream.remotePort
|
### cleartextStream.remotePort
|
||||||
|
|
||||||
The numeric representation of the remote port. For example, `443`.
|
The numeric representation of the remote port. For example, `443`.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<style>
|
<style>
|
||||||
@ -12,8 +12,8 @@
|
|||||||
<script src="../sh_javascript.min.js"></script>
|
<script src="../sh_javascript.min.js"></script>
|
||||||
<link type="image/x-icon" rel="icon" href="../favicon.ico">
|
<link type="image/x-icon" rel="icon" href="../favicon.ico">
|
||||||
<link type="image/x-icon" rel="shortcut icon" href="../favicon.ico">
|
<link type="image/x-icon" rel="shortcut icon" href="../favicon.ico">
|
||||||
<link type="text/css" rel="stylesheet" href="../pipe.css">
|
<link rel="stylesheet" href="../pipe.css">
|
||||||
<link type="text/css" rel="stylesheet" href="../sh_vim-dark.css">
|
<link rel="stylesheet" href="../sh_vim-dark.css">
|
||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="application/rss+xml"
|
type="application/rss+xml"
|
||||||
title="node blog"
|
title="node blog"
|
||||||
|
@ -157,7 +157,7 @@ var http = require('http');
|
|||||||
http.createServer(function (req, res) {
|
http.createServer(function (req, res) {
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
res.end('Hello World\n');
|
res.end('Hello World\n');
|
||||||
}).listen(1337, "127.0.0.1");
|
}).listen(1337, '127.0.0.1');
|
||||||
console.log('Server running at http://127.0.0.1:1337/');</pre>
|
console.log('Server running at http://127.0.0.1:1337/');</pre>
|
||||||
|
|
||||||
<p>To run the server, put the code into a file <code>example.js</code> and execute it with the <code>node</code> program:</p>
|
<p>To run the server, put the code into a file <code>example.js</code> and execute it with the <code>node</code> program:</p>
|
||||||
@ -171,11 +171,11 @@ Server running at http://127.0.0.1:1337/</pre>
|
|||||||
var net = require('net');
|
var net = require('net');
|
||||||
|
|
||||||
var server = net.createServer(function (socket) {
|
var server = net.createServer(function (socket) {
|
||||||
socket.write("Echo server\r\n");
|
socket.write('Echo server\r\n');
|
||||||
socket.pipe(socket);
|
socket.pipe(socket);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen(1337, "127.0.0.1");</pre>
|
server.listen(1337, '127.0.0.1');</pre>
|
||||||
|
|
||||||
<!-- <p>Ready to dig in? <a href="">Download the latest version</a> of node.js or learn how other organizations are <a href="">using the technology</a>.</p> -->
|
<!-- <p>Ready to dig in? <a href="">Download the latest version</a> of node.js or learn how other organizations are <a href="">using the technology</a>.</p> -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,24 +1,21 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<style type="text/css">
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
ul {
|
ul {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js?ver=3.1.3'></script>
|
|
||||||
<script type="text/javascript" src="../sh_main.js"></script>
|
|
||||||
<script type="text/javascript" src="../sh_javascript.min.js"></script>
|
|
||||||
<link type="image/x-icon" rel="icon" href="../favicon.ico">
|
<link type="image/x-icon" rel="icon" href="../favicon.ico">
|
||||||
<link type="image/x-icon" rel="shortcut icon" href="../favicon.ico">
|
<link type="image/x-icon" rel="shortcut icon" href="../favicon.ico">
|
||||||
<link type="text/css" rel="stylesheet" href="../pipe.css">
|
<link rel="stylesheet" href="../pipe.css">
|
||||||
<link type="text/css" rel="stylesheet" href="../sh_vim-dark.css">
|
<link rel="stylesheet" href="../sh_vim-dark.css">
|
||||||
<link rel="alternate"
|
<link rel="alternate"
|
||||||
type="application/rss+xml"
|
type="application/rss+xml"
|
||||||
title="node blog"
|
title="node blog"
|
||||||
href="http://feeds.feedburner.com/nodejs/123123123">
|
href="http://feeds.feedburner.com/nodejs/123123123">
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
||||||
<title>node.js</title>
|
<title>node.js</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="int" id="logos">
|
<body class="int" id="logos">
|
||||||
@ -88,10 +85,7 @@
|
|||||||
<p>Copyright <a href="http://joyent.com">Joyent, Inc</a>., Node.js is a <a href="/trademark-policy.pdf">trademark of Joyent, Inc</a>., <a href="https://raw.github.com/joyent/node/v0.7.4/LICENSE">View License</a></p>
|
<p>Copyright <a href="http://joyent.com">Joyent, Inc</a>., Node.js is a <a href="/trademark-policy.pdf">trademark of Joyent, Inc</a>., <a href="https://raw.github.com/joyent/node/v0.7.4/LICENSE">View License</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var gaJsHost = (("https:" == document.location.protocol) ?
|
var gaJsHost = (("https:" == document.location.protocol) ?
|
||||||
"https://ssl." : "http://www.");
|
"https://ssl." : "http://www.");
|
||||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
@ -102,6 +96,5 @@
|
|||||||
pageTracker._trackPageview();
|
pageTracker._trackPageview();
|
||||||
} catch(err) {}
|
} catch(err) {}
|
||||||
</script>
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
</body></html>
|
|
||||||
|
@ -175,7 +175,7 @@ Socket.prototype.send = function(buffer,
|
|||||||
if (callback) callback(err);
|
if (callback) callback(err);
|
||||||
self.emit('error', err);
|
self.emit('error', err);
|
||||||
}
|
}
|
||||||
else {
|
else if (self._handle) {
|
||||||
var req = self._handle.send(buffer, offset, length, port, ip);
|
var req = self._handle.send(buffer, offset, length, port, ip);
|
||||||
if (req) {
|
if (req) {
|
||||||
req.oncomplete = afterSend;
|
req.oncomplete = afterSend;
|
||||||
|
@ -359,6 +359,8 @@ IncomingMessage.prototype._addHeaderLine = function(field, value) {
|
|||||||
case 'pragma':
|
case 'pragma':
|
||||||
case 'link':
|
case 'link':
|
||||||
case 'www-authenticate':
|
case 'www-authenticate':
|
||||||
|
case 'sec-websocket-extensions':
|
||||||
|
case 'sec-websocket-protocol':
|
||||||
if (field in dest) {
|
if (field in dest) {
|
||||||
dest[field] += ', ' + value;
|
dest[field] += ', ' + value;
|
||||||
} else {
|
} else {
|
||||||
|
@ -97,7 +97,13 @@ if (isWindows) {
|
|||||||
// directories. If we've resolved a drive letter but not yet an
|
// directories. If we've resolved a drive letter but not yet an
|
||||||
// absolute path, get cwd for that drive. We're sure the device is not
|
// absolute path, get cwd for that drive. We're sure the device is not
|
||||||
// an unc path at this points, because unc paths are always absolute.
|
// an unc path at this points, because unc paths are always absolute.
|
||||||
path = process._cwdForDrive(resolvedDevice[0]);
|
path = process.env['=' + resolvedDevice];
|
||||||
|
// Verify that a drive-local cwd was found and that it actually points
|
||||||
|
// to our drive. If not, default to the drive's root.
|
||||||
|
if (!path || path.slice(0, 3).toLowerCase() !==
|
||||||
|
resolvedDevice.toLowerCase() + '\\') {
|
||||||
|
path = resolvedDevice + '\\';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip empty and invalid entries
|
// Skip empty and invalid entries
|
||||||
|
@ -525,8 +525,13 @@ REPLServer.prototype.complete = function(line, callback) {
|
|||||||
}
|
}
|
||||||
// works for non-objects
|
// works for non-objects
|
||||||
try {
|
try {
|
||||||
var p = Object.getPrototypeOf(obj);
|
|
||||||
var sentinel = 5;
|
var sentinel = 5;
|
||||||
|
var p;
|
||||||
|
if (typeof obj == 'object') {
|
||||||
|
p = Object.getPrototypeOf(obj);
|
||||||
|
} else {
|
||||||
|
p = obj.constructor ? obj.constructor.prototype : null;
|
||||||
|
}
|
||||||
while (p !== null) {
|
while (p !== null) {
|
||||||
memberGroups.push(Object.getOwnPropertyNames(p));
|
memberGroups.push(Object.getOwnPropertyNames(p));
|
||||||
p = Object.getPrototypeOf(p);
|
p = Object.getPrototypeOf(p);
|
||||||
|
80
lib/tls.js
80
lib/tls.js
@ -27,6 +27,14 @@ var stream = require('stream');
|
|||||||
var END_OF_FILE = 42;
|
var END_OF_FILE = 42;
|
||||||
var assert = require('assert').ok;
|
var assert = require('assert').ok;
|
||||||
|
|
||||||
|
// Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations
|
||||||
|
// every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more
|
||||||
|
// renegotations are seen. The settings are applied to all remote client
|
||||||
|
// connections.
|
||||||
|
exports.CLIENT_RENEG_LIMIT = 3;
|
||||||
|
exports.CLIENT_RENEG_WINDOW = 600;
|
||||||
|
|
||||||
|
|
||||||
var debug;
|
var debug;
|
||||||
if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) {
|
if (process.env.NODE_DEBUG && /tls/.test(process.env.NODE_DEBUG)) {
|
||||||
debug = function(a) { console.error('TLS:', a); };
|
debug = function(a) { console.error('TLS:', a); };
|
||||||
@ -539,6 +547,37 @@ EncryptedStream.prototype._pusher = function(pool, offset, length) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function onhandshakestart() {
|
||||||
|
debug('onhandshakestart');
|
||||||
|
|
||||||
|
var self = this, ssl = this.ssl;
|
||||||
|
ssl.handshakes++;
|
||||||
|
|
||||||
|
if (ssl.handshakes === 1) {
|
||||||
|
function timeout() {
|
||||||
|
ssl.handshakes = 0;
|
||||||
|
ssl.timer = null;
|
||||||
|
}
|
||||||
|
ssl.timer = setTimeout(timeout, exports.CLIENT_RENEG_WINDOW * 1000);
|
||||||
|
}
|
||||||
|
else if (ssl.handshakes >= exports.CLIENT_RENEG_LIMIT) {
|
||||||
|
// Defer the error event to the next tick. We're being called from OpenSSL's
|
||||||
|
// state machine and OpenSSL is not re-entrant. We cannot allow the user's
|
||||||
|
// callback to destroy the connection right now, it would crash and burn.
|
||||||
|
process.nextTick(function() {
|
||||||
|
var err = new Error('TLS session renegotiation attack detected.');
|
||||||
|
if (self.cleartext) self.cleartext.emit('error', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function onhandshakedone() {
|
||||||
|
// for future use
|
||||||
|
debug('onhandshakedone');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a pair of streams to do encrypted communication.
|
* Provides a pair of streams to do encrypted communication.
|
||||||
*/
|
*/
|
||||||
@ -585,6 +624,13 @@ function SecurePair(credentials, isServer, requestCert, rejectUnauthorized,
|
|||||||
this._isServer ? this._requestCert : options.servername,
|
this._isServer ? this._requestCert : options.servername,
|
||||||
this._rejectUnauthorized);
|
this._rejectUnauthorized);
|
||||||
|
|
||||||
|
if (this._isServer) {
|
||||||
|
this.ssl.onhandshakestart = onhandshakestart.bind(this);
|
||||||
|
this.ssl.onhandshakedone = onhandshakedone.bind(this);
|
||||||
|
this.ssl.handshakes = 0;
|
||||||
|
this.ssl.timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (process.features.tls_sni) {
|
if (process.features.tls_sni) {
|
||||||
if (this._isServer && options.SNICallback) {
|
if (this._isServer && options.SNICallback) {
|
||||||
this.ssl.setSNICallback(options.SNICallback);
|
this.ssl.setSNICallback(options.SNICallback);
|
||||||
@ -720,25 +766,29 @@ SecurePair.prototype.maybeInitFinished = function() {
|
|||||||
|
|
||||||
|
|
||||||
SecurePair.prototype.destroy = function() {
|
SecurePair.prototype.destroy = function() {
|
||||||
if (this._doneFlag) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
this._doneFlag = true;
|
if (!this._doneFlag) {
|
||||||
this.ssl.error = null;
|
this._doneFlag = true;
|
||||||
this.ssl.close();
|
|
||||||
this.ssl = null;
|
|
||||||
|
|
||||||
self.encrypted.writable = self.encrypted.readable = false;
|
if (this.ssl.timer) {
|
||||||
self.cleartext.writable = self.cleartext.readable = false;
|
clearTimeout(this.ssl.timer);
|
||||||
|
this.ssl.timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
process.nextTick(function() {
|
this.ssl.error = null;
|
||||||
self.cleartext.emit('end');
|
this.ssl.close();
|
||||||
self.encrypted.emit('close');
|
this.ssl = null;
|
||||||
self.cleartext.emit('close');
|
|
||||||
});
|
self.encrypted.writable = self.encrypted.readable = false;
|
||||||
|
self.cleartext.writable = self.cleartext.readable = false;
|
||||||
|
|
||||||
|
process.nextTick(function() {
|
||||||
|
self.cleartext.emit('end');
|
||||||
|
self.encrypted.emit('close');
|
||||||
|
self.cleartext.emit('close');
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
1
node.gyp
1
node.gyp
@ -155,6 +155,7 @@
|
|||||||
'FD_SETSIZE=1024',
|
'FD_SETSIZE=1024',
|
||||||
# we need to use node's preferred "win32" rather than gyp's preferred "win"
|
# we need to use node's preferred "win32" rather than gyp's preferred "win"
|
||||||
'PLATFORM="win32"',
|
'PLATFORM="win32"',
|
||||||
|
'_UNICODE=1',
|
||||||
],
|
],
|
||||||
'libraries': [ '-lpsapi.lib' ]
|
'libraries': [ '-lpsapi.lib' ]
|
||||||
},{ # POSIX
|
},{ # POSIX
|
||||||
|
241
src/node.cc
241
src/node.cc
@ -1290,76 +1290,6 @@ static Handle<Value> Cwd(const Arguments& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static Handle<Value> CwdForDrive(const Arguments& args) {
|
|
||||||
HandleScope scope;
|
|
||||||
|
|
||||||
if (args.Length() < 1) {
|
|
||||||
Local<Value> exception = Exception::Error(
|
|
||||||
String::New("process._cwdForDrive takes exactly 1 argument."));
|
|
||||||
return ThrowException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
Local<String> driveLetter = args[0]->ToString();
|
|
||||||
if (driveLetter->Length() != 1) {
|
|
||||||
Local<Value> exception = Exception::Error(
|
|
||||||
String::New("Drive name should be 1 character."));
|
|
||||||
return ThrowException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
char drive;
|
|
||||||
|
|
||||||
driveLetter->WriteAscii(&drive, 0, 1, 0);
|
|
||||||
if (drive >= 'a' && drive <= 'z') {
|
|
||||||
// Convert to uppercase
|
|
||||||
drive += 'A' - 'a';
|
|
||||||
} else if (drive < 'A' || drive > 'Z') {
|
|
||||||
// Not a letter
|
|
||||||
Local<Value> exception = Exception::Error(
|
|
||||||
String::New("Drive name should be a letter."));
|
|
||||||
return ThrowException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR env_key[] = L"=X:";
|
|
||||||
env_key[1] = (WCHAR) drive;
|
|
||||||
|
|
||||||
DWORD len = GetEnvironmentVariableW(env_key, NULL, 0);
|
|
||||||
if (len == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
|
|
||||||
// There is no current directory for that drive. Default to drive + ":\".
|
|
||||||
Local<String> cwd = String::Concat(String::New(&drive, 1),
|
|
||||||
String::New(":\\"));
|
|
||||||
return scope.Close(cwd);
|
|
||||||
|
|
||||||
} else if (len == 0) {
|
|
||||||
// Error
|
|
||||||
Local<Value> exception = Exception::Error(
|
|
||||||
String::New(winapi_strerror(GetLastError())));
|
|
||||||
return ThrowException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR* buffer = new WCHAR[len];
|
|
||||||
if (buffer == NULL) {
|
|
||||||
Local<Value> exception = Exception::Error(
|
|
||||||
String::New("Out of memory."));
|
|
||||||
return ThrowException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD len2 = GetEnvironmentVariableW(env_key, buffer, len);
|
|
||||||
if (len2 == 0 || len2 >= len) {
|
|
||||||
// Error
|
|
||||||
delete[] buffer;
|
|
||||||
Local<Value> exception = Exception::Error(
|
|
||||||
String::New(winapi_strerror(GetLastError())));
|
|
||||||
return ThrowException(exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
Local<String> cwd = String::New(reinterpret_cast<uint16_t*>(buffer), len2);
|
|
||||||
delete[] buffer;
|
|
||||||
return scope.Close(cwd);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static Handle<Value> Umask(const Arguments& args) {
|
static Handle<Value> Umask(const Arguments& args) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
unsigned int old;
|
unsigned int old;
|
||||||
@ -1883,12 +1813,28 @@ static void ProcessTitleSetter(Local<String> property,
|
|||||||
|
|
||||||
static Handle<Value> EnvGetter(Local<String> property,
|
static Handle<Value> EnvGetter(Local<String> property,
|
||||||
const AccessorInfo& info) {
|
const AccessorInfo& info) {
|
||||||
|
HandleScope scope;
|
||||||
|
#ifdef __POSIX__
|
||||||
String::Utf8Value key(property);
|
String::Utf8Value key(property);
|
||||||
const char* val = getenv(*key);
|
const char* val = getenv(*key);
|
||||||
if (val) {
|
if (val) {
|
||||||
HandleScope scope;
|
|
||||||
return scope.Close(String::New(val));
|
return scope.Close(String::New(val));
|
||||||
}
|
}
|
||||||
|
#else // _WIN32
|
||||||
|
String::Value key(property);
|
||||||
|
WCHAR buffer[32767]; // The maximum size allowed for environment variables.
|
||||||
|
DWORD result = GetEnvironmentVariableW(reinterpret_cast<WCHAR*>(*key),
|
||||||
|
buffer,
|
||||||
|
ARRAY_SIZE(buffer));
|
||||||
|
// If result >= sizeof buffer the buffer was too small. That should never
|
||||||
|
// happen. If result == 0 and result != ERROR_SUCCESS the variable was not
|
||||||
|
// not found.
|
||||||
|
if ((result > 0 || GetLastError() == ERROR_SUCCESS) &&
|
||||||
|
result < ARRAY_SIZE(buffer)) {
|
||||||
|
return scope.Close(String::New(reinterpret_cast<uint16_t*>(buffer), result));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Not found
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1897,66 +1843,82 @@ static Handle<Value> EnvSetter(Local<String> property,
|
|||||||
Local<Value> value,
|
Local<Value> value,
|
||||||
const AccessorInfo& info) {
|
const AccessorInfo& info) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
#ifdef __POSIX__
|
||||||
String::Utf8Value key(property);
|
String::Utf8Value key(property);
|
||||||
String::Utf8Value val(value);
|
String::Utf8Value val(value);
|
||||||
|
|
||||||
#ifdef __POSIX__
|
|
||||||
setenv(*key, *val, 1);
|
setenv(*key, *val, 1);
|
||||||
#else // __WIN32__
|
#else // _WIN32
|
||||||
int n = key.length() + val.length() + 2;
|
String::Value key(property);
|
||||||
char* pair = new char[n];
|
String::Value val(value);
|
||||||
snprintf(pair, n, "%s=%s", *key, *val);
|
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
|
||||||
int r = _putenv(pair);
|
// Environment variables that start with '=' are read-only.
|
||||||
if (r) {
|
if (key_ptr[0] != L'=') {
|
||||||
fprintf(stderr, "error putenv: '%s'\n", pair);
|
SetEnvironmentVariableW(key_ptr, reinterpret_cast<WCHAR*>(*val));
|
||||||
}
|
}
|
||||||
delete [] pair;
|
|
||||||
#endif
|
#endif
|
||||||
|
// Whether it worked or not, always return rval.
|
||||||
return value;
|
return scope.Close(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Handle<Integer> EnvQuery(Local<String> property,
|
static Handle<Integer> EnvQuery(Local<String> property,
|
||||||
const AccessorInfo& info) {
|
const AccessorInfo& info) {
|
||||||
|
HandleScope scope;
|
||||||
|
#ifdef __POSIX__
|
||||||
String::Utf8Value key(property);
|
String::Utf8Value key(property);
|
||||||
if (getenv(*key)) {
|
if (getenv(*key)) {
|
||||||
HandleScope scope;
|
|
||||||
return scope.Close(Integer::New(None));
|
return scope.Close(Integer::New(None));
|
||||||
}
|
}
|
||||||
return Handle<Integer>();
|
#else // _WIN32
|
||||||
|
String::Value key(property);
|
||||||
|
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
|
||||||
|
if (GetEnvironmentVariableW(key_ptr, NULL, 0) > 0 ||
|
||||||
|
GetLastError() == ERROR_SUCCESS) {
|
||||||
|
if (key_ptr[0] == L'=') {
|
||||||
|
// Environment variables that start with '=' are hidden and read-only.
|
||||||
|
return scope.Close(Integer::New(v8::ReadOnly ||
|
||||||
|
v8::DontDelete ||
|
||||||
|
v8::DontEnum));
|
||||||
|
} else {
|
||||||
|
return scope.Close(Integer::New(None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// Not found
|
||||||
|
return scope.Close(Handle<Integer>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Handle<Boolean> EnvDeleter(Local<String> property,
|
static Handle<Boolean> EnvDeleter(Local<String> property,
|
||||||
const AccessorInfo& info) {
|
const AccessorInfo& info) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
|
||||||
String::Utf8Value key(property);
|
|
||||||
|
|
||||||
if (getenv(*key)) {
|
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
unsetenv(*key); // prototyped as `void unsetenv(const char*)` on some platforms
|
String::Utf8Value key(property);
|
||||||
|
// prototyped as `void unsetenv(const char*)` on some platforms
|
||||||
|
if (unsetenv(*key) < 0) {
|
||||||
|
// Deletion failed. Return true if the key wasn't there in the first place,
|
||||||
|
// false if it is still there.
|
||||||
|
return scope.Close(Boolean::New(getenv(*key) == NULL));
|
||||||
|
};
|
||||||
#else
|
#else
|
||||||
int n = key.length() + 2;
|
String::Value key(property);
|
||||||
char* pair = new char[n];
|
WCHAR* key_ptr = reinterpret_cast<WCHAR*>(*key);
|
||||||
snprintf(pair, n, "%s=", *key);
|
if (key_ptr[0] == L'=' || !SetEnvironmentVariableW(key_ptr, NULL)) {
|
||||||
int r = _putenv(pair);
|
// Deletion failed. Return true if the key wasn't there in the first place,
|
||||||
if (r) {
|
// false if it is still there.
|
||||||
fprintf(stderr, "error unsetenv: '%s'\n", pair);
|
bool rv = GetEnvironmentVariableW(key_ptr, NULL, NULL) == 0 &&
|
||||||
}
|
GetLastError() != ERROR_SUCCESS;
|
||||||
delete [] pair;
|
return scope.Close(Boolean::New(rv));
|
||||||
#endif
|
|
||||||
return True();
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return False();
|
// It worked
|
||||||
|
return v8::True();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
|
static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
#ifdef __POSIX__
|
||||||
int size = 0;
|
int size = 0;
|
||||||
while (environ[size]) size++;
|
while (environ[size]) size++;
|
||||||
|
|
||||||
@ -1968,7 +1930,32 @@ static Handle<Array> EnvEnumerator(const AccessorInfo& info) {
|
|||||||
const int length = s ? s - var : strlen(var);
|
const int length = s ? s - var : strlen(var);
|
||||||
env->Set(i, String::New(var, length));
|
env->Set(i, String::New(var, length));
|
||||||
}
|
}
|
||||||
|
#else // _WIN32
|
||||||
|
WCHAR* environment = GetEnvironmentStringsW();
|
||||||
|
if (environment == NULL) {
|
||||||
|
// This should not happen.
|
||||||
|
return scope.Close(Handle<Array>());
|
||||||
|
}
|
||||||
|
Local<Array> env = Array::New();
|
||||||
|
WCHAR* p = environment;
|
||||||
|
int i = 0;
|
||||||
|
while (*p != NULL) {
|
||||||
|
WCHAR *s;
|
||||||
|
if (*p == L'=') {
|
||||||
|
// If the key starts with '=' it is a hidden environment variable.
|
||||||
|
p += wcslen(p) + 1;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
s = wcschr(p, L'=');
|
||||||
|
}
|
||||||
|
if (!s) {
|
||||||
|
s = p + wcslen(p);
|
||||||
|
}
|
||||||
|
env->Set(i++, String::New(reinterpret_cast<uint16_t*>(p), s - p));
|
||||||
|
p = s + wcslen(s) + 1;
|
||||||
|
}
|
||||||
|
FreeEnvironmentStringsW(environment);
|
||||||
|
#endif
|
||||||
return scope.Close(env);
|
return scope.Close(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2127,10 +2114,6 @@ Handle<Object> SetupProcessObject(int argc, char *argv[]) {
|
|||||||
NODE_SET_METHOD(process, "chdir", Chdir);
|
NODE_SET_METHOD(process, "chdir", Chdir);
|
||||||
NODE_SET_METHOD(process, "cwd", Cwd);
|
NODE_SET_METHOD(process, "cwd", Cwd);
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
NODE_SET_METHOD(process, "_cwdForDrive", CwdForDrive);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
NODE_SET_METHOD(process, "umask", Umask);
|
NODE_SET_METHOD(process, "umask", Umask);
|
||||||
|
|
||||||
#ifdef __POSIX__
|
#ifdef __POSIX__
|
||||||
@ -2416,13 +2399,14 @@ DWORD WINAPI EnableDebugThreadProc(void* arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int GetDebugSignalHandlerMappingName(DWORD pid, char* buf, size_t buf_len) {
|
static int GetDebugSignalHandlerMappingName(DWORD pid, wchar_t* buf,
|
||||||
return snprintf(buf, buf_len, "node-debug-handler-%u", pid);
|
size_t buf_len) {
|
||||||
|
return _snwprintf(buf, buf_len, L"node-debug-handler-%u", pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int RegisterDebugSignalHandler() {
|
static int RegisterDebugSignalHandler() {
|
||||||
char mapping_name[32];
|
wchar_t mapping_name[32];
|
||||||
HANDLE mapping_handle;
|
HANDLE mapping_handle;
|
||||||
DWORD pid;
|
DWORD pid;
|
||||||
LPTHREAD_START_ROUTINE* handler;
|
LPTHREAD_START_ROUTINE* handler;
|
||||||
@ -2431,11 +2415,11 @@ static int RegisterDebugSignalHandler() {
|
|||||||
|
|
||||||
if (GetDebugSignalHandlerMappingName(pid,
|
if (GetDebugSignalHandlerMappingName(pid,
|
||||||
mapping_name,
|
mapping_name,
|
||||||
sizeof mapping_name) < 0) {
|
ARRAY_SIZE(mapping_name)) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping_handle = CreateFileMappingA(INVALID_HANDLE_VALUE,
|
mapping_handle = CreateFileMappingW(INVALID_HANDLE_VALUE,
|
||||||
NULL,
|
NULL,
|
||||||
PAGE_READWRITE,
|
PAGE_READWRITE,
|
||||||
0,
|
0,
|
||||||
@ -2445,11 +2429,12 @@ static int RegisterDebugSignalHandler() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler = (LPTHREAD_START_ROUTINE*) MapViewOfFile(mapping_handle,
|
handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
|
||||||
FILE_MAP_ALL_ACCESS,
|
MapViewOfFile(mapping_handle,
|
||||||
0,
|
FILE_MAP_ALL_ACCESS,
|
||||||
0,
|
0,
|
||||||
sizeof *handler);
|
0,
|
||||||
|
sizeof *handler));
|
||||||
if (handler == NULL) {
|
if (handler == NULL) {
|
||||||
CloseHandle(mapping_handle);
|
CloseHandle(mapping_handle);
|
||||||
return -1;
|
return -1;
|
||||||
@ -2470,7 +2455,7 @@ static Handle<Value> DebugProcess(const Arguments& args) {
|
|||||||
HANDLE process = NULL;
|
HANDLE process = NULL;
|
||||||
HANDLE thread = NULL;
|
HANDLE thread = NULL;
|
||||||
HANDLE mapping = NULL;
|
HANDLE mapping = NULL;
|
||||||
char mapping_name[32];
|
wchar_t mapping_name[32];
|
||||||
LPTHREAD_START_ROUTINE* handler = NULL;
|
LPTHREAD_START_ROUTINE* handler = NULL;
|
||||||
|
|
||||||
if (args.Length() != 1) {
|
if (args.Length() != 1) {
|
||||||
@ -2492,22 +2477,24 @@ static Handle<Value> DebugProcess(const Arguments& args) {
|
|||||||
|
|
||||||
if (GetDebugSignalHandlerMappingName(pid,
|
if (GetDebugSignalHandlerMappingName(pid,
|
||||||
mapping_name,
|
mapping_name,
|
||||||
sizeof mapping_name) < 0) {
|
ARRAY_SIZE(mapping_name)) < 0) {
|
||||||
rv = ThrowException(ErrnoException(errno, "sprintf"));
|
rv = ThrowException(ErrnoException(errno, "sprintf"));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping = OpenFileMapping(FILE_MAP_READ, FALSE, mapping_name);
|
mapping = OpenFileMappingW(FILE_MAP_READ, FALSE, mapping_name);
|
||||||
if (mapping == NULL) {
|
if (mapping == NULL) {
|
||||||
rv = ThrowException(WinapiErrnoException(GetLastError(), "sprintf"));
|
rv = ThrowException(WinapiErrnoException(GetLastError(),
|
||||||
|
"OpenFileMappingW"));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler = (LPTHREAD_START_ROUTINE*) MapViewOfFile(mapping,
|
handler = reinterpret_cast<LPTHREAD_START_ROUTINE*>(
|
||||||
FILE_MAP_READ,
|
MapViewOfFile(mapping,
|
||||||
0,
|
FILE_MAP_READ,
|
||||||
0,
|
0,
|
||||||
sizeof *handler);
|
0,
|
||||||
|
sizeof *handler));
|
||||||
if (handler == NULL || *handler == NULL) {
|
if (handler == NULL || *handler == NULL) {
|
||||||
rv = ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
|
rv = ThrowException(WinapiErrnoException(GetLastError(), "MapViewOfFile"));
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -908,6 +908,8 @@ Handle<Value> Connection::New(const Arguments& args) {
|
|||||||
|
|
||||||
SSL_set_app_data(p->ssl_, p);
|
SSL_set_app_data(p->ssl_, p);
|
||||||
|
|
||||||
|
if (is_server) SSL_set_info_callback(p->ssl_, SSLInfoCallback);
|
||||||
|
|
||||||
#ifdef OPENSSL_NPN_NEGOTIATED
|
#ifdef OPENSSL_NPN_NEGOTIATED
|
||||||
if (is_server) {
|
if (is_server) {
|
||||||
// Server should advertise NPN protocols
|
// Server should advertise NPN protocols
|
||||||
@ -970,6 +972,20 @@ Handle<Value> Connection::New(const Arguments& args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Connection::SSLInfoCallback(const SSL *ssl, int where, int ret) {
|
||||||
|
if (where & SSL_CB_HANDSHAKE_START) {
|
||||||
|
HandleScope scope;
|
||||||
|
Connection* c = static_cast<Connection*>(SSL_get_app_data(ssl));
|
||||||
|
MakeCallback(c->handle_, "onhandshakestart", 0, NULL);
|
||||||
|
}
|
||||||
|
if (where & SSL_CB_HANDSHAKE_DONE) {
|
||||||
|
HandleScope scope;
|
||||||
|
Connection* c = static_cast<Connection*>(SSL_get_app_data(ssl));
|
||||||
|
MakeCallback(c->handle_, "onhandshakedone", 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Value> Connection::EncIn(const Arguments& args) {
|
Handle<Value> Connection::EncIn(const Arguments& args) {
|
||||||
HandleScope scope;
|
HandleScope scope;
|
||||||
|
|
||||||
|
@ -190,6 +190,8 @@ class Connection : ObjectWrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void SSLInfoCallback(const SSL *ssl, int where, int ret);
|
||||||
|
|
||||||
BIO *bio_read_;
|
BIO *bio_read_;
|
||||||
BIO *bio_write_;
|
BIO *bio_write_;
|
||||||
SSL *ssl_;
|
SSL *ssl_;
|
||||||
|
@ -21,6 +21,47 @@
|
|||||||
|
|
||||||
#include <node.h>
|
#include <node.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
int wmain(int argc, wchar_t *wargv[]) {
|
||||||
|
// Convert argv to to UTF8
|
||||||
|
char** argv = new char*[argc];
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
// Compute the size of the required buffer
|
||||||
|
DWORD size = WideCharToMultiByte(CP_UTF8,
|
||||||
|
0,
|
||||||
|
wargv[i],
|
||||||
|
-1,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (size == 0) {
|
||||||
|
// This should never happen.
|
||||||
|
fprintf(stderr, "Could not convert arguments to utf8.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
// Do the actual conversion
|
||||||
|
argv[i] = new char[size];
|
||||||
|
DWORD result = WideCharToMultiByte(CP_UTF8,
|
||||||
|
0,
|
||||||
|
wargv[i],
|
||||||
|
-1,
|
||||||
|
argv[i],
|
||||||
|
size,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (result == 0) {
|
||||||
|
// This should never happen.
|
||||||
|
fprintf(stderr, "Could not convert arguments to utf8.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now that conversion is done, we can finally start.
|
||||||
|
return node::Start(argc, argv);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// UNIX
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
return node::Start(argc, argv);
|
return node::Start(argc, argv);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -204,10 +204,7 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
|
|||||||
PipeWrap* client_wrap =
|
PipeWrap* client_wrap =
|
||||||
static_cast<PipeWrap*>(client_obj->GetPointerFromInternalField(0));
|
static_cast<PipeWrap*>(client_obj->GetPointerFromInternalField(0));
|
||||||
|
|
||||||
int r = uv_accept(handle, (uv_stream_t*)&client_wrap->handle_);
|
if (uv_accept(handle, (uv_stream_t*)&client_wrap->handle_)) return;
|
||||||
|
|
||||||
// uv_accept should always work.
|
|
||||||
assert(r == 0);
|
|
||||||
|
|
||||||
// Successful accept. Call the onconnection callback in JavaScript land.
|
// Successful accept. Call the onconnection callback in JavaScript land.
|
||||||
Local<Value> argv[1] = { client_obj };
|
Local<Value> argv[1] = { client_obj };
|
||||||
|
@ -366,10 +366,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
|
|||||||
TCPWrap* client_wrap =
|
TCPWrap* client_wrap =
|
||||||
static_cast<TCPWrap*>(client_obj->GetPointerFromInternalField(0));
|
static_cast<TCPWrap*>(client_obj->GetPointerFromInternalField(0));
|
||||||
|
|
||||||
int r = uv_accept(handle, (uv_stream_t*)&client_wrap->handle_);
|
if (uv_accept(handle, (uv_stream_t*)&client_wrap->handle_)) return;
|
||||||
|
|
||||||
// uv_accept should always work.
|
|
||||||
assert(r == 0);
|
|
||||||
|
|
||||||
// Successful accept. Call the onconnection callback in JavaScript land.
|
// Successful accept. Call the onconnection callback in JavaScript land.
|
||||||
argv[0] = client_obj;
|
argv[0] = client_obj;
|
||||||
|
100
test/pummel/test-tls-ci-reneg-attack.js
Normal file
100
test/pummel/test-tls-ci-reneg-attack.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// 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 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 server = tls.createServer(options, function(conn) {
|
||||||
|
conn.on('error', function(err) {
|
||||||
|
console.error('Caught exception: ' + err);
|
||||||
|
assert(/TLS session renegotiation attack/.test(err));
|
||||||
|
conn.destroy();
|
||||||
|
});
|
||||||
|
conn.pipe(conn);
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
child.stderr.on('data', function(data) {
|
||||||
|
handshakes += (('' + data).match(/verify return:1/g) || []).length;
|
||||||
|
if (handshakes === 2) spam();
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('exit', function() {
|
||||||
|
// with a renegotiation limit <= 1, we always see 4 handshake markers:
|
||||||
|
// two for the initial handshake and another two for the attempted
|
||||||
|
// renegotiation
|
||||||
|
assert.equal(handshakes, 2 * Math.max(2, tls.CLIENT_RENEG_LIMIT));
|
||||||
|
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, 250);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -1,77 +0,0 @@
|
|||||||
// 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.
|
|
||||||
|
|
||||||
// This test starts two clustered HTTP servers on the same port. It expects the
|
|
||||||
// first cluster to succeed and the second cluster to fail with EADDRINUSE.
|
|
||||||
|
|
||||||
var common = require('../common');
|
|
||||||
var assert = require('assert');
|
|
||||||
var cluster = require('cluster');
|
|
||||||
var fork = require('child_process').fork;
|
|
||||||
var http = require('http');
|
|
||||||
|
|
||||||
var id = process.argv[2];
|
|
||||||
|
|
||||||
if (!id) {
|
|
||||||
var a = fork(__filename, ['one']);
|
|
||||||
var b = fork(__filename, ['two']);
|
|
||||||
|
|
||||||
a.on('message', function(m) {
|
|
||||||
assert.equal(m, 'READY');
|
|
||||||
b.send('START');
|
|
||||||
});
|
|
||||||
|
|
||||||
var ok = false;
|
|
||||||
|
|
||||||
b.on('message', function(m) {
|
|
||||||
assert.equal(m, 'EADDRINUSE');
|
|
||||||
a.kill();
|
|
||||||
b.kill();
|
|
||||||
ok = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
process.on('exit', function() {
|
|
||||||
a.kill();
|
|
||||||
b.kill();
|
|
||||||
assert(ok);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (id === 'one') {
|
|
||||||
if (cluster.isMaster) cluster.fork();
|
|
||||||
http.createServer(assert.fail).listen(common.PORT, function() {
|
|
||||||
process.send('READY');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (id === 'two') {
|
|
||||||
if (cluster.isMaster) cluster.fork();
|
|
||||||
process.on('message', function(m) {
|
|
||||||
assert.equal(m, 'START');
|
|
||||||
var server = http.createServer(assert.fail);
|
|
||||||
server.listen(common.PORT, assert.fail);
|
|
||||||
server.on('error', function(e) {
|
|
||||||
assert.equal(e.code, 'EADDRINUSE');
|
|
||||||
process.send(e.code);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(0); // bad command line argument
|
|
||||||
}
|
|
35
test/simple/test-dgram-close.js
Normal file
35
test/simple/test-dgram-close.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Ensure that if a dgram socket is closed before the DNS lookup completes, it
|
||||||
|
// won't crash.
|
||||||
|
|
||||||
|
var assert = require('assert'),
|
||||||
|
common = require('../common'),
|
||||||
|
dgram = require('dgram');
|
||||||
|
|
||||||
|
var buf = new Buffer(1024);
|
||||||
|
buf.fill(42);
|
||||||
|
|
||||||
|
var socket = dgram.createSocket('udp4');
|
||||||
|
|
||||||
|
socket.send(buf, 0, buf.length, common.port, 'localhost');
|
||||||
|
socket.close();
|
@ -33,6 +33,8 @@ var srv = http.createServer(function(req, res) {
|
|||||||
assert.equal(req.headers['www-authenticate'], 'foo, bar, baz');
|
assert.equal(req.headers['www-authenticate'], 'foo, bar, baz');
|
||||||
assert.equal(req.headers['x-foo'], 'bingo');
|
assert.equal(req.headers['x-foo'], 'bingo');
|
||||||
assert.equal(req.headers['x-bar'], 'banjo, bango');
|
assert.equal(req.headers['x-bar'], 'banjo, bango');
|
||||||
|
assert.equal(req.headers['sec-websocket-protocol'], 'chat, share');
|
||||||
|
assert.equal(req.headers['sec-websocket-extensions'], 'foo; 1, bar; 2, baz');
|
||||||
|
|
||||||
res.writeHead(200, {'Content-Type' : 'text/plain'});
|
res.writeHead(200, {'Content-Type' : 'text/plain'});
|
||||||
res.end('EOF');
|
res.end('EOF');
|
||||||
@ -57,7 +59,12 @@ srv.listen(common.PORT, function() {
|
|||||||
['WWW-AUTHENTICATE', 'baz'],
|
['WWW-AUTHENTICATE', 'baz'],
|
||||||
['x-foo', 'bingo'],
|
['x-foo', 'bingo'],
|
||||||
['x-bar', 'banjo'],
|
['x-bar', 'banjo'],
|
||||||
['x-bar', 'bango']
|
['x-bar', 'bango'],
|
||||||
|
['sec-websocket-protocol', 'chat'],
|
||||||
|
['sec-websocket-protocol', 'share'],
|
||||||
|
['sec-websocket-extensions', 'foo; 1'],
|
||||||
|
['sec-websocket-extensions', 'bar; 2'],
|
||||||
|
['sec-websocket-extensions', 'baz']
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -180,3 +180,12 @@ testMe.complete('inner.o', function(error, data) {
|
|||||||
assert.deepEqual(data, doesNotBreak);
|
assert.deepEqual(data, doesNotBreak);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
putIn.run(['.clear']);
|
||||||
|
|
||||||
|
// make sure tab completion works on non-Objects
|
||||||
|
putIn.run([
|
||||||
|
'var str = "test";'
|
||||||
|
]);
|
||||||
|
testMe.complete('str.len', function(error, data) {
|
||||||
|
assert.deepEqual(data, [ [ 'str.length' ], 'str.len' ]);
|
||||||
|
});
|
||||||
|
156
test/simple/test-tls-over-http-tunnel.js
Normal file
156
test/simple/test-tls-over-http-tunnel.js
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!process.versions.openssl) {
|
||||||
|
console.error('Skipping because node compiled without OpenSSL.');
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
var common = require('../common');
|
||||||
|
var assert = require('assert');
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var net = require('net');
|
||||||
|
var http = require('http');
|
||||||
|
var https = require('https');
|
||||||
|
|
||||||
|
var proxyPort = common.PORT + 1;
|
||||||
|
var gotRequest = false;
|
||||||
|
|
||||||
|
var key = fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem');
|
||||||
|
var cert = fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem');
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
key: key,
|
||||||
|
cert: cert
|
||||||
|
};
|
||||||
|
|
||||||
|
var server = https.createServer(options, function(req, res) {
|
||||||
|
console.log('SERVER: got request');
|
||||||
|
res.writeHead(200, {
|
||||||
|
'content-type': 'text/plain',
|
||||||
|
});
|
||||||
|
console.log('SERVER: sending response');
|
||||||
|
res.end('hello world\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
var proxy = net.createServer(function(clientSocket) {
|
||||||
|
console.log('PROXY: got a client connection');
|
||||||
|
|
||||||
|
var serverSocket = null;
|
||||||
|
|
||||||
|
clientSocket.on('data', function(chunk) {
|
||||||
|
if (!serverSocket) {
|
||||||
|
// Verify the CONNECT request
|
||||||
|
assert.equal('CONNECT localhost:' + common.PORT + ' HTTP/1.1\r\n' +
|
||||||
|
'Proxy-Connections: keep-alive\r\nContent-Length:' +
|
||||||
|
' 0\r\nHost: localhost:' + proxyPort + '\r\n\r\n',
|
||||||
|
chunk);
|
||||||
|
|
||||||
|
console.log('PROXY: got CONNECT request');
|
||||||
|
console.log('PROXY: creating a tunnel');
|
||||||
|
|
||||||
|
// create the tunnel
|
||||||
|
serverSocket = net.connect(common.PORT, function() {
|
||||||
|
console.log('PROXY: replying to client CONNECT request');
|
||||||
|
|
||||||
|
// Send the response
|
||||||
|
clientSocket.write('HTTP/1.1 200 OK\r\nProxy-Connections: keep' +
|
||||||
|
'-alive\r\nConnections: keep-alive\r\nVia: ' +
|
||||||
|
'localhost:' + proxyPort + '\r\n\r\n');
|
||||||
|
});
|
||||||
|
|
||||||
|
serverSocket.on('data', function(chunk) {
|
||||||
|
clientSocket.write(chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
serverSocket.on('end', function() {
|
||||||
|
clientSocket.destroy();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
serverSocket.write(chunk);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
clientSocket.on('end', function() {
|
||||||
|
serverSocket.destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
server.listen(common.PORT);
|
||||||
|
|
||||||
|
proxy.listen(proxyPort, function() {
|
||||||
|
console.log('CLIENT: Making CONNECT request');
|
||||||
|
|
||||||
|
http.request({
|
||||||
|
port: proxyPort,
|
||||||
|
method: 'CONNECT',
|
||||||
|
path: 'localhost:' + common.PORT,
|
||||||
|
headers: {
|
||||||
|
'Proxy-Connections': 'keep-alive',
|
||||||
|
'Content-Length': 0
|
||||||
|
}
|
||||||
|
}, function(res) {
|
||||||
|
assert.equal(200, res.statusCode);
|
||||||
|
console.log('CLIENT: got CONNECT response');
|
||||||
|
|
||||||
|
// detach the socket
|
||||||
|
res.socket.emit('agentRemove');
|
||||||
|
res.socket.removeAllListeners('data');
|
||||||
|
res.socket.removeAllListeners('close');
|
||||||
|
res.socket.removeAllListeners('error');
|
||||||
|
res.socket.removeAllListeners('drain');
|
||||||
|
res.socket.removeAllListeners('end');
|
||||||
|
res.socket.ondata = null;
|
||||||
|
res.socket.onend = null;
|
||||||
|
res.socket.ondrain = null;
|
||||||
|
|
||||||
|
console.log('CLIENT: Making HTTPS request');
|
||||||
|
|
||||||
|
https.get({
|
||||||
|
path: '/foo',
|
||||||
|
key: key,
|
||||||
|
cert: cert,
|
||||||
|
socket: res.socket, // reuse the socket
|
||||||
|
agent: false,
|
||||||
|
}, function(res) {
|
||||||
|
assert.equal(200, res.statusCode);
|
||||||
|
|
||||||
|
res.on('data', function(chunk) {
|
||||||
|
assert.equal('hello world\n', chunk);
|
||||||
|
console.log('CLIENT: got HTTPS response');
|
||||||
|
gotRequest = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on('end', function() {
|
||||||
|
proxy.close();
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
}).end();
|
||||||
|
}).end();
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('exit', function() {
|
||||||
|
assert.ok(gotRequest);
|
||||||
|
});
|
39
vcbuild.bat
39
vcbuild.bat
@ -26,26 +26,27 @@ set upload=
|
|||||||
|
|
||||||
:next-arg
|
:next-arg
|
||||||
if "%1"=="" goto args-done
|
if "%1"=="" goto args-done
|
||||||
if /i "%1"=="debug" set config=Debug&goto arg-ok
|
if /i "%1"=="debug" set config=Debug&goto arg-ok
|
||||||
if /i "%1"=="release" set config=Release&goto arg-ok
|
if /i "%1"=="release" set config=Release&goto arg-ok
|
||||||
if /i "%1"=="clean" set target=Clean&goto arg-ok
|
if /i "%1"=="clean" set target=Clean&goto arg-ok
|
||||||
if /i "%1"=="ia32" set target_arch=ia32&goto arg-ok
|
if /i "%1"=="ia32" set target_arch=ia32&goto arg-ok
|
||||||
if /i "%1"=="x86" set target_arch=ia32&goto arg-ok
|
if /i "%1"=="x86" set target_arch=ia32&goto arg-ok
|
||||||
if /i "%1"=="x64" set target_arch=x64&goto arg-ok
|
if /i "%1"=="x64" set target_arch=x64&goto arg-ok
|
||||||
if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok
|
if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok
|
||||||
if /i "%1"=="nobuild" set nobuild=1&goto arg-ok
|
if /i "%1"=="nobuild" set nobuild=1&goto arg-ok
|
||||||
if /i "%1"=="nosign" set nosign=1&goto arg-ok
|
if /i "%1"=="nosign" set nosign=1&goto arg-ok
|
||||||
if /i "%1"=="nosnapshot" set nosnapshot=1&goto arg-ok
|
if /i "%1"=="nosnapshot" set nosnapshot=1&goto arg-ok
|
||||||
if /i "%1"=="test-uv" set test=test-uv&goto arg-ok
|
if /i "%1"=="test-uv" set test=test-uv&goto arg-ok
|
||||||
if /i "%1"=="test-internet"set test=test-internet&goto arg-ok
|
if /i "%1"=="test-internet" set test=test-internet&goto arg-ok
|
||||||
if /i "%1"=="test-pummel" set test=test-pummel&goto arg-ok
|
if /i "%1"=="test-pummel" set test=test-pummel&goto arg-ok
|
||||||
if /i "%1"=="test-simple" set test=test-simple&goto arg-ok
|
if /i "%1"=="test-simple" set test=test-simple&goto arg-ok
|
||||||
if /i "%1"=="test-message" set test=test-message&goto arg-ok
|
if /i "%1"=="test-message" set test=test-message&goto arg-ok
|
||||||
if /i "%1"=="test-all" set test=test-all&goto arg-ok
|
if /i "%1"=="test-all" set test=test-all&goto arg-ok
|
||||||
if /i "%1"=="test" set test=test&goto arg-ok
|
if /i "%1"=="test" set test=test&goto arg-ok
|
||||||
if /i "%1"=="msi" set msi=1&goto arg-ok
|
if /i "%1"=="msi" set msi=1&goto arg-ok
|
||||||
if /i "%1"=="upload" set upload=1&goto arg-ok
|
if /i "%1"=="upload" set upload=1&goto arg-ok
|
||||||
|
|
||||||
|
echo Warning: ignoring invalid command line option `%1`.
|
||||||
|
|
||||||
:arg-ok
|
:arg-ok
|
||||||
shift
|
shift
|
||||||
|
Loading…
x
Reference in New Issue
Block a user