mirror of
https://github.com/nodejs/node.git
synced 2024-12-01 16:10:02 +01:00
123 lines
3.5 KiB
JavaScript
123 lines
3.5 KiB
JavaScript
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);
|
|
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;
|
|
};
|
|
|