[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