Skip to content

Commit

Permalink
Upgrade STARTTLS handling to TLSSocket
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Mar 27, 2015
1 parent 272c50b commit 6c8c5c7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 150 deletions.
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
language: node_js
node_js:
- "0.10"
- 0.12
- iojs

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Hoodiecrow is a scriptable IMAP server for client integration testing. It offers
[![Build Status](https://secure.travis-ci.org/andris9/hoodiecrow.png)](http://travis-ci.org/andris9/hoodiecrow)
[![NPM version](https://badge.fury.io/js/hoodiecrow.png)](http://badge.fury.io/js/hoodiecrow)

STARTTLS does not play well with OpenSSL 1.0+, this is why the Travis-CI builds fail as well. No idea how to fix this - with OpenSSL 0.9 everything works fine. I've had some success with using TLSSocket for STARTTLS on the server side but this only works in Node 0.11+ so I haven't yet included it in Hoodiecrow.
STARTTLS requires Node *0.12* or *iojs* as it uses [tls.TLSSocket](https://nodejs.org/api/tls.html#tls_class_tls_tlssocket) API.

# Usage

Expand Down
66 changes: 35 additions & 31 deletions lib/server.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use strict";

var Stream = require("stream").Stream,
util = require("util"),
net = require("net"),
tls = require("tls"),
fs = require("fs"),
imapHandler = require("imap-handler"),
starttls = require("./starttls");
var Stream = require("stream").Stream;
var util = require("util");
var net = require("net");
var tls = require("tls");
var fs = require("fs");
var imapHandler = require("imap-handler");
//var starttls = require("./starttls");

module.exports = function(options) {
return new IMAPServer(options);
Expand Down Expand Up @@ -759,7 +759,6 @@ function IMAPConnection(server, socket) {
this.state = "Not Authenticated";

this.secureConnection = !!this.options.secureConnection;
this._ignoreData = false;

this._remainder = "";
this._command = "";
Expand Down Expand Up @@ -808,13 +807,6 @@ IMAPConnection.prototype.onError = function(err) {
IMAPConnection.prototype.onData = function(chunk) {
var match, str;

if (this._ignoreData) {
// If TLS upgrade is initiated do not process current buffer
this._remainder = "";
this._command = "";
return;
}

str = (chunk || "").toString("binary");

if (this._literalRemaining) {
Expand Down Expand Up @@ -884,26 +876,38 @@ IMAPConnection.prototype.onNotify = function(notification) {
};

IMAPConnection.prototype.upgradeConnection = function(callback) {
this._ignoreData = true;
var pair = starttls(this.socket, this.options.credentials, (function(socket) {
this._ignoreData = false;
this._remainder = "";
this.upgrading = true;

this.socket = socket;
this.socket.on("data", this.onData.bind(this));
this.secureConnection = true;
var secureContext = tls.createSecureContext(this.options.credentials);
var socketOptions = {
secureContext: secureContext,
isServer: true,
server: this.server.server,

if (!socket.authorized && this.options.debug) {
console.log("WARNING: TLS ERROR (" + socket.authorizationError + ")");
// throws if SNICallback is missing, so we set a default callback
SNICallback: function(servername, cb) {
cb(null, secureContext);
}
};

// remove all listeners from the original socket besides the error handler
this.socket.removeAllListeners();
this.socket.on("error", this.onError.bind(this));

// upgrade connection
var secureSocket = new tls.TLSSocket(this.socket, socketOptions);

secureSocket.on("close", this.onClose.bind(this));
secureSocket.on("error", this.onError.bind(this));
secureSocket.on("clientError", this.onError.bind(this));

secureSocket.on("secure", function() {
this.secureConnection = true;
this.socket = secureSocket;
this.upgrading = false;
this.socket.on("data", this.onData.bind(this));
callback();
}).bind(this));
pair.on("error", function(err) {
console.log(err);
if (this.socket && !this.socket.destroyed) {
this.socket.end();
}
});
}.bind(this));
};

IMAPConnection.prototype.processNotifications = function(data) {
Expand Down
117 changes: 0 additions & 117 deletions lib/starttls.js

This file was deleted.

0 comments on commit 6c8c5c7

Please sign in to comment.