mirror of https://github.com/lukechilds/node.git
Ryan Dahl
14 years ago
2 changed files with 158 additions and 0 deletions
@ -0,0 +1,129 @@ |
|||
var crypto = require('crypto'); |
|||
var net = require('net'); |
|||
var events = require('events'); |
|||
var inherits = require('util').inherits; |
|||
|
|||
// TODO: support anonymous (nocert) and PSK
|
|||
// TODO: how to proxy maxConnections?
|
|||
|
|||
|
|||
// Options:
|
|||
// - unauthorizedPeers. Boolean, default to false.
|
|||
// - key. string.
|
|||
// - cert: string.
|
|||
// - ca: string or array of strings.
|
|||
//
|
|||
// emit 'authorized'
|
|||
// function (cleartext) { }
|
|||
//
|
|||
// emit 'unauthorized'
|
|||
// function (cleartext, verifyError) { }
|
|||
// Possible errors:
|
|||
// "UNABLE_TO_GET_ISSUER_CERT", "UNABLE_TO_GET_CRL",
|
|||
// "UNABLE_TO_DECRYPT_CERT_SIGNATURE", "UNABLE_TO_DECRYPT_CRL_SIGNATURE",
|
|||
// "UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", "CERT_SIGNATURE_FAILURE",
|
|||
// "CRL_SIGNATURE_FAILURE", "CERT_NOT_YET_VALID" "CERT_HAS_EXPIRED",
|
|||
// "CRL_NOT_YET_VALID", "CRL_HAS_EXPIRED" "ERROR_IN_CERT_NOT_BEFORE_FIELD",
|
|||
// "ERROR_IN_CERT_NOT_AFTER_FIELD", "ERROR_IN_CRL_LAST_UPDATE_FIELD",
|
|||
// "ERROR_IN_CRL_NEXT_UPDATE_FIELD", "OUT_OF_MEM",
|
|||
// "DEPTH_ZERO_SELF_SIGNED_CERT", "SELF_SIGNED_CERT_IN_CHAIN",
|
|||
// "UNABLE_TO_GET_ISSUER_CERT_LOCALLY", "UNABLE_TO_VERIFY_LEAF_SIGNATURE",
|
|||
// "CERT_CHAIN_TOO_LONG", "CERT_REVOKED" "INVALID_CA",
|
|||
// "PATH_LENGTH_EXCEEDED", "INVALID_PURPOSE" "CERT_UNTRUSTED",
|
|||
// "CERT_REJECTED"
|
|||
//
|
|||
//
|
|||
// TODO:
|
|||
// cleartext.credentials (by mirroring from pair object)
|
|||
// cleartext.getCertificate() (by mirroring from pair.credentials.context)
|
|||
function Server ( /* [options], listener */) { |
|||
var options, listener; |
|||
if (typeof arguments[0] == "object") { |
|||
options = arguments[0]; |
|||
listener = arguments[1]; |
|||
} else if (typeof arguments[0] == "function") { |
|||
options = {}; |
|||
listener = arguments[0]; |
|||
} |
|||
|
|||
if (!(this instanceof Server)) return new Server(options, listener); |
|||
|
|||
var self = this; |
|||
|
|||
// constructor call
|
|||
net.Server.call(this, function (socket) { |
|||
var creds = crypto.createCredentials({ key: self.key, |
|||
cert: self.cert, |
|||
ca: self.ca }); |
|||
creds.context.setCiphers('RC4-SHA:AES128-SHA:AES256-SHA'); |
|||
|
|||
var pair = crypto.createPair(creds, |
|||
true, |
|||
!self.unauthorizedPeers); |
|||
pair.encrypted.pipe(socket); |
|||
socket.pipe(pair.encrypted); |
|||
|
|||
pair.on('secure', function () { |
|||
var verifyError = pair._ssl.verifyError(); |
|||
|
|||
if (verifyError) { |
|||
if (self.unauthorizedPeers) { |
|||
self.emit('unauthorized', pair.cleartext, verifyError); |
|||
} else { |
|||
console.error("REJECT PEER. verify error: %s", verifyError); |
|||
socket.destroy(); |
|||
} |
|||
} else { |
|||
self.emit('authorized', pair.cleartext); |
|||
} |
|||
}); |
|||
|
|||
pair.on('error', function (e) { |
|||
console.log('pair got error: ' + e); |
|||
|
|||
// TODO better way to get error code.
|
|||
if (/no shared cipher/.test(e.message)) { |
|||
; |
|||
} else { |
|||
self.emit('error', e); |
|||
} |
|||
}); |
|||
|
|||
pair.cleartext.on('error', function(err) { |
|||
console.log('cleartext got error: ' + err); |
|||
}); |
|||
|
|||
pair.encrypted.on('error', function(err) { |
|||
console.log('encrypted got error: ' + err); |
|||
}); |
|||
}); |
|||
|
|||
if (listener) { |
|||
this.on('authorized', listener); |
|||
this.on('unauthorized', listener); |
|||
} |
|||
|
|||
// Handle option defaults:
|
|||
|
|||
this.setOptions(options); |
|||
} |
|||
|
|||
inherits(Server, net.Server); |
|||
exports.Server = Server; |
|||
exports.createServer = function (options, listener) { |
|||
return new Server(options, listener); |
|||
}; |
|||
|
|||
|
|||
Server.prototype.setOptions = function (options) { |
|||
if (typeof options.unauthorizedPeers == "boolean") { |
|||
this.unauthorizedPeers = options.unauthorizedPeers; |
|||
} else { |
|||
this.unauthorizedPeers = false; |
|||
} |
|||
|
|||
if (options.key) this.key = options.key; |
|||
if (options.cert) this.cert = options.cert; |
|||
if (options.ca) this.ca = options.ca; |
|||
}; |
|||
|
@ -0,0 +1,29 @@ |
|||
// Example of new TLS API. Test with:
|
|||
//
|
|||
// openssl s_client -connect localhost:12346 -key test/fixtures/agent.key -cert test/fixtures/agent.crt
|
|||
// openssl s_client -connect localhost:12346
|
|||
//
|
|||
var common = require('../common'); |
|||
var tls = require('tls'); |
|||
var fs = require('fs'); |
|||
var join = require('path').join; |
|||
|
|||
var key = fs.readFileSync(join(common.fixturesDir, "agent.key")).toString(); |
|||
var cert = fs.readFileSync(join(common.fixturesDir, "agent.crt")).toString(); |
|||
|
|||
s = tls.Server({ key: key, cert: cert, unauthorizedPeers: false }); |
|||
|
|||
s.listen(common.PORT, function () { |
|||
console.log("TLS server on 127.0.0.1:%d", common.PORT); |
|||
}); |
|||
|
|||
|
|||
s.on('authorized', function (c) { |
|||
console.log("authed connection"); |
|||
c.end("bye authorized friend.\n"); |
|||
}); |
|||
|
|||
s.on('unauthorized', function (c, e) { |
|||
console.log("unauthed connection: %s", e); |
|||
c.end("bye unauthorized person.\n"); |
|||
}); |
Loading…
Reference in new issue