[Pkg-javascript-commits] [node-starttls] 01/02: Imported Upstream version 1.0.1
Thorsten Alteholz
alteholz at moszumanska.debian.org
Sun Apr 3 14:47:48 UTC 2016
This is an automated email from the git hooks/post-receive script.
alteholz pushed a commit to branch master
in repository node-starttls.
commit f6ec115baec30fa9651d46c894d6757ac8318a8c
Author: Thorsten Alteholz <debian at alteholz.de>
Date: Sun Apr 3 16:47:45 2016 +0200
Imported Upstream version 1.0.1
---
.npmignore | 2 +
.travis.yml | 7 +++
Makefile | 11 ++++
README.md | 75 ++++++++++++++++++++++++
lib/starttls.js | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
package.json | 44 ++++++++++++++
test/starttls.js | 122 ++++++++++++++++++++++++++++++++++++++
7 files changed, 436 insertions(+)
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..646ac51
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,2 @@
+.DS_Store
+node_modules/
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..915e68d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,7 @@
+language: node_js
+
+node_js:
+ - "0.12"
+ - "0.10"
+
+script: make test
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1f3d82c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+test: lib/*.js node_modules
+ ./node_modules/.bin/mocha \
+ --reporter dot \
+ --check-leaks \
+ --ui tdd
+
+node_modules: package.json
+ npm install
+ touch $@
+
+.PHONY: test
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..b981dd8
--- /dev/null
+++ b/README.md
@@ -0,0 +1,75 @@
+# Start TLS #
+
+[![Build Status](https://travis-ci.org/mattcg/starttls.png?branch=master)](https://travis-ci.org/mattcg/starttls)
+
+Upgrade a regular [`net.Stream`](http://nodejs.org/api/net.html#net_class_net_socket) connection to a secure [`tls`](http://nodejs.org/api/tls.html) connection.
+
+Based on code by [Andris Reinman](https://github.com/andris9/rai/blob/master/lib/starttls.js), itself based on an older version by [Nathan Rajlich](https://gist.github.com/TooTallNate/848444).
+
+## Usage ##
+
+This library has one method and accepts either an options hash or a prepared socket as the first argument. It returns a [`SecurePair`](http://nodejs.org/api/tls.html#tls_class_securepair).
+
+### starttls(options, [onSecure]), starttls(socket, [onSecure]) ###
+
+The following options are supported:
+
+- `socket` - if not provided, a socket will be created using [`net.createConnection`](http://nodejs.org/api/net.html#net_net_createconnection_options_connectionlistener)
+- `host` - used to perform automatic certificate identity checking, to guard against MITM attacks
+- `port` - only used to create a socket (along with the `host` option) if `socket` is not provided
+- `pair` - if you want to provide your own [`SecurePair`](http://nodejs.org/api/tls.html#tls_class_securepair) object
+
+The `onSecure` callback is optional and receives `null` or an error object as the first argument (see below for error cases). Within the callback context, `this` refers to the same [`SecurePair`](http://nodejs.org/api/tls.html#tls_class_securepair) object returned by `starttls`.
+
+```javascript
+var net = require('net');
+var starttls = require('starttls');
+var options = {
+ port: 21,
+ host: example.com
+};
+
+net.createConnection(options, function() {
+ options.socket = this;
+ starttls(options, function(err) {
+ if (err) {
+
+ // Something bad happened!
+ return;
+ }
+
+ this.cleartext.write('garbage');
+ });
+});
+```
+
+You should always check for an error before writing to the stream to avoid man-in-the-middle attacks. Errors are produced in the following cases:
+
+- the certificate authority authorization check failed or was negative
+- the server identity check was negative
+
+If you only pass a socket object, server identity checking will not be performed automatically. In that case you should perform the check manually.
+
+```javascript
+starttls(socket, function(err) {
+ if (!tls.checkServerIdentity(host, this.cleartext.getPeerCertificate())) {
+
+ // Hostname mismatch!
+ // Report error and end connection...
+ }
+});
+```
+
+## Example ##
+
+See [socks5-https-client](https://github.com/mattcg/socks5-https-client) for use-case.
+
+## Tests ##
+
+Run `make test` or `npm test` to run tests.
+
+## License ##
+
+Portions of this code copyright (c) 2012, Andris Reinman and copyright (c) 2011, Nathan Rajlich.
+
+Modified and redistributed under an [MIT license](http://mattcg.mit-license.org/).
diff --git a/lib/starttls.js b/lib/starttls.js
new file mode 100644
index 0000000..72d74d9
--- /dev/null
+++ b/lib/starttls.js
@@ -0,0 +1,175 @@
+/**
+ * Original: https://gist.github.com/TooTallNate/848444
+ * Adapted: https://github.com/andris9/rai/blob/master/lib/starttls.js
+ *
+ * @overview
+ * @author Matthew Caruana Galizia <m at m.cg>
+ * @author Andris Reinman <andris.reinman at gmail.com>
+ * @author Nathan Rajlich <nathan at tootallnate.net>
+ * @copyright Copyright (c) 2012, Andris Reinman
+ * @copyright Copyright (c) 2011, Nathan Rajlich
+ * @license MIT
+ * @preserve
+ */
+
+'use strict';
+
+/*jshint node:true*/
+/*global exports:true*/
+
+var net = require('net');
+var tls = require('tls');
+var crypto = require('crypto');
+
+module.exports = exports = function(options, onSecure) {
+ var socket, credentials, securePair;
+
+ if (options instanceof net.Socket) {
+ socket = options;
+ options = {
+ socket: socket
+ };
+ } else if (options.socket) {
+ socket = options.socket;
+ } else {
+ socket = options.socket = net.createConnection(options);
+ }
+
+ if (options.pair) {
+ securePair = options.pair;
+ } else {
+
+ // Node v0.12.0 deprecated crypto.createCredentials.
+ if (tls.createSecureContext) {
+ credentials = tls.createSecureContext();
+ } else {
+ credentials = crypto.createCredentials();
+ }
+
+ securePair = tls.createSecurePair(credentials, false);
+ options.pair = securePair;
+ }
+
+ // In Node < 0.9.0, socket.readable is undefined.
+ if (socket.readable || undefined === socket.readable) {
+ return startTls(options, onSecure);
+ }
+
+ // In Node > 0.9.0, if the socket is still unconnected then wait for connect.
+ socket.once('connect', function() {
+ startTls(options, onSecure);
+ });
+
+ return securePair;
+};
+
+function startTls(options, onSecure) {
+ var socket, host, securePair, clearText;
+
+ socket = options.socket;
+ host = options.host;
+ securePair = options.pair;
+
+ socket.ondata = null;
+ socket.removeAllListeners('data');
+
+ clearText = pipe(securePair, socket);
+
+ securePair.once('secure', function() {
+ var err;
+
+ // A cleartext stream has the boolean property 'authorized' to determine if it was verified by the CA. If 'authorized' is false, a property 'authorizationError' is set on the stream.
+ err = securePair.ssl.verifyError();
+ if (err) {
+ clearText.authorized = false;
+ clearText.authorizationError = err;
+ } else {
+ clearText.authorized = true;
+ }
+
+ // The callback parameter is optional.
+ if (!onSecure) {
+ return;
+ }
+
+ if (host) {
+ err = tls.checkServerIdentity(host, clearText.getPeerCertificate());
+
+ // As of node v0.12.0, `tls.checkServerIdentity` returns an error object if there was an error, `undefined` otherwise.
+ // On previous versions it returned `false` if there was an error and `true` otherwise.
+ if (false === err) {
+ err = new Error('Server identity mismatch: invalid certificate for ' + host + '.');
+ } else if (true === err) {
+ err = null;
+ }
+ }
+
+ onSecure.call(securePair, err);
+ });
+
+ clearText._controlReleased = true;
+
+ return securePair;
+}
+
+function forwardEvents(events, emitterSource, emitterDestination) {
+ var i, l, event, handler, forwardEvent;
+
+ forwardEvent = function() {
+ this.emit.apply(this, arguments);
+ };
+
+ for (i = 0, l = events.length; i < l; i++) {
+ event = events[i];
+ handler = forwardEvent.bind(emitterDestination, event);
+
+ emitterSource.on(event, handler);
+ }
+}
+
+function removeEvents(events, emitterSource) {
+ var i, l;
+
+ for (i = 0, l = events.length; i < l; i++){
+ emitterSource.removeAllListeners(events[i]);
+ }
+}
+
+function pipe(securePair, socket) {
+ var clearText, onError, onClose, events;
+
+ events = ['timeout', 'end', 'drain'];
+ clearText = securePair.cleartext;
+
+ onError = function(err) {
+ if (clearText._controlReleased) {
+ clearText.emit('error', err);
+ }
+ };
+
+ onClose = function() {
+ socket.removeListener('error', onError);
+ socket.removeListener('close', onClose);
+ removeEvents(events, socket);
+ };
+
+ // Forward event emissions from the socket to the cleartext stream.
+ forwardEvents(events, socket, clearText);
+ socket.on('error', onError);
+ socket.on('close', onClose);
+
+ securePair.on('error', function(err) {
+ onError(err);
+ });
+
+ securePair.encrypted.pipe(socket);
+ socket.pipe(securePair.encrypted);
+
+ securePair.fd = socket.fd;
+
+ clearText.socket = socket;
+ clearText.encrypted = securePair.encrypted;
+ clearText.authorized = false;
+
+ return clearText;
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..f13f640
--- /dev/null
+++ b/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "starttls",
+ "description": "Upgrade a regular `net.Stream` connection to a secure `tls` connection.",
+ "version": "1.0.1",
+ "main": "lib/starttls.js",
+ "homepage": "https://github.com/mattcg/starttls",
+ "implements": ["CommonJS/Modules/1.0"],
+ "contributors": [
+ {
+ "name": "Nathan Rajlich",
+ "email": "nathan at tootallnate.net"
+ },
+ {
+ "name": "Andris Reinman",
+ "email": "andris.reinman at gmail.com"
+ },
+ {
+ "name": "Matthew Caruana Galizia",
+ "email": "m at m.cg"
+ }
+ ],
+ "keywords": [
+ "tls", "stream", "net", "upgrade", "ssl"
+ ],
+ "scripts": {
+ "test": "make test"
+ },
+ "devDependencies": {
+ "mocha": "1.x"
+ },
+ "bugs": {
+ "url": "https://github.com/mattcg/starttls/issues"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/mattcg/starttls.git"
+ },
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://opensource.org/licenses/MIT"
+ }
+ ]
+}
diff --git a/test/starttls.js b/test/starttls.js
new file mode 100644
index 0000000..1e735bc
--- /dev/null
+++ b/test/starttls.js
@@ -0,0 +1,122 @@
+/**
+ * @overview
+ * @author Matthew Caruana Galizia <m at m.cg>
+ * @copyright Copyright (c) 2013, Matthew Caruana Galizia
+ * @license MIT
+ * @preserve
+ */
+
+'use strict';
+
+/*jshint node:true*/
+/*global test, suite*/
+
+var assert = require('assert');
+var net = require('net');
+var tls = require('tls');
+
+var starttls = require('../lib/starttls');
+
+suite('starttls tests', function() {
+ var options;
+
+ options = {
+ host: 'www.google.com',
+ port: 443
+ };
+
+ test('simple connect with prepared socket', function(done) {
+ net.createConnection(options, function() {
+ var pair;
+
+ pair = starttls(this, function(err) {
+ assert.ifError(err);
+ assert(pair.cleartext.authorized);
+ assert.ifError(pair.cleartext.authorizationError);
+
+ assert(this === pair);
+
+ done();
+ });
+ });
+ });
+
+ test('identity check with prepared socket', function(done) {
+ net.createConnection(options, function() {
+ var pair;
+
+ pair = starttls(this, function(err) {
+ var cert, check;
+
+ cert = pair.cleartext.getPeerCertificate();
+
+ // Returns error or undefined on node v0.12.0 and true or false on previous versions.
+ check = tls.checkServerIdentity(options.host, cert);
+ assert.equal(check === true || typeof check === 'undefined', true);
+
+ check = tls.checkServerIdentity('www.facebook.com', cert);
+ assert.equal(check === false || check instanceof Error, true);
+
+ done();
+ });
+ });
+ });
+
+ test('simple connect with options and prepared socket', function(done) {
+ starttls({
+ socket: net.createConnection(options)
+ }, function(err) {
+ var pair = this;
+
+ assert.ifError(err);
+
+ assert(pair.cleartext);
+ assert(pair.cleartext.authorized);
+ assert.ifError(pair.cleartext.authorizationError);
+
+ done();
+ });
+ });
+
+ test('simple connect with options', function(done) {
+ starttls(options, function(err) {
+ var pair = this;
+
+ assert.ifError(err);
+
+ assert(pair.cleartext);
+ assert(pair.cleartext.authorized);
+ assert.ifError(pair.cleartext.authorizationError);
+
+ done();
+ });
+ });
+
+ test('host is checked', function(done) {
+ var options;
+
+ options = {
+
+ // Take advantage of the fact that this domain has an SSL certificate error.
+ host: 'projects.icij.org.s3.amazonaws.com',
+ port: 443
+ };
+
+ starttls(options, function(err) {
+ assert(err);
+ done();
+ });
+ });
+
+ test('host is checked even if socket is provided', function(done) {
+ var falseHost = 'www.facebook.com';
+
+ starttls({
+ host: falseHost,
+ socket: net.createConnection(options)
+ }, function(err) {
+ assert(err);
+ done();
+ });
+ });
+});
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-starttls.git
More information about the Pkg-javascript-commits
mailing list