| var http = require('http'); |
| var https = require('https'); |
| var net = require('net'); |
| var fs = require('fs'); |
| var path = require('path'); |
| var should = require('should'); |
| var tunnel = require('../index'); |
| |
| function readPem(file) { |
| return fs.readFileSync(path.join('test/keys', file + '.pem')); |
| } |
| |
| var serverKey = readPem('server2-key'); |
| var serverCert = readPem('server2-cert'); |
| var serverCA = readPem('ca1-cert'); |
| var proxyKey = readPem('proxy2-key'); |
| var proxyCert = readPem('proxy2-cert'); |
| var proxyCA = readPem('ca2-cert'); |
| var client1Key = readPem('client1-key'); |
| var client1Cert = readPem('client1-cert'); |
| var client1CA = readPem('ca3-cert'); |
| var client2Key = readPem('client2-key'); |
| var client2Cert = readPem('client2-cert'); |
| var client2CA = readPem('ca4-cert'); |
| |
| describe('HTTPS over HTTPS authentication failed', function() { |
| it('should finish without error', function(done) { |
| var serverPort = 3008; |
| var proxyPort = 3009; |
| var serverConnect = 0; |
| var proxyConnect = 0; |
| var clientRequest = 0; |
| var clientConnect = 0; |
| var clientError = 0; |
| var server; |
| var proxy; |
| |
| server = https.createServer({ |
| key: serverKey, |
| cert: serverCert, |
| ca: [client1CA], |
| requestCert: true, |
| rejectUnauthorized: true |
| }, function(req, res) { |
| tunnel.debug('SERVER: got request', req.url); |
| ++serverConnect; |
| req.on('data', function(data) { |
| }); |
| req.on('end', function() { |
| res.writeHead(200); |
| res.end('Hello, ' + serverConnect); |
| tunnel.debug('SERVER: sending response'); |
| }); |
| req.resume(); |
| }); |
| //server.addContext('server2', { |
| // key: serverKey, |
| // cert: serverCert, |
| // ca: [client1CA], |
| //}); |
| server.listen(serverPort, setupProxy); |
| |
| function setupProxy() { |
| proxy = https.createServer({ |
| key: proxyKey, |
| cert: proxyCert, |
| ca: [client2CA], |
| requestCert: true, |
| rejectUnauthorized: true |
| }, function(req, res) { |
| should.fail(); |
| }); |
| //proxy.addContext('proxy2', { |
| // key: proxyKey, |
| // cert: proxyCert, |
| // ca: [client2CA], |
| //}); |
| proxy.on('upgrade', onConnect); // for v0.6 |
| proxy.on('connect', onConnect); // for v0.7 or later |
| |
| function onConnect(req, clientSocket, head) { |
| req.method.should.equal('CONNECT'); |
| req.url.should.equal('localhost:' + serverPort); |
| req.headers.should.not.have.property('transfer-encoding'); |
| ++proxyConnect; |
| |
| var serverSocket = net.connect(serverPort, function() { |
| tunnel.debug('PROXY: replying to client CONNECT request'); |
| clientSocket.write('HTTP/1.1 200 Connection established\r\n\r\n'); |
| clientSocket.pipe(serverSocket); |
| serverSocket.write(head); |
| serverSocket.pipe(clientSocket); |
| // workaround, see #2524 |
| serverSocket.on('end', function() { |
| clientSocket.end(); |
| }); |
| }); |
| } |
| proxy.listen(proxyPort, setupClient); |
| } |
| |
| function setupClient() { |
| function doRequest(name, options, host) { |
| tunnel.debug('CLIENT: Making HTTPS request (%s)', name); |
| ++clientRequest; |
| var agent = tunnel.httpsOverHttps(options); |
| var req = https.get({ |
| host: 'localhost', |
| port: serverPort, |
| path: '/' + encodeURIComponent(name), |
| headers: { |
| host: host ? host : 'localhost', |
| }, |
| rejectUnauthorized: true, |
| agent: agent |
| }, function(res) { |
| tunnel.debug('CLIENT: got HTTPS response (%s)', name); |
| ++clientConnect; |
| res.on('data', function(data) { |
| }); |
| res.on('end', function() { |
| req.emit('finish'); |
| }); |
| res.resume(); |
| }); |
| req.on('error', function(err) { |
| tunnel.debug('CLIENT: failed HTTP response (%s)', name, err); |
| ++clientError; |
| req.emit('finish'); |
| }); |
| req.on('finish', function() { |
| if (clientConnect + clientError === clientRequest) { |
| proxy.close(); |
| server.close(); |
| } |
| }); |
| } |
| |
| doRequest('no cert origin nor proxy', { // invalid |
| maxSockets: 1, |
| ca: [serverCA], |
| rejectUnauthorized: true, |
| // no certificate for origin server |
| proxy: { |
| port: proxyPort, |
| ca: [proxyCA], |
| rejectUnauthorized: true, |
| headers: { |
| host: 'proxy2' |
| } |
| // no certificate for proxy |
| } |
| }, 'server2'); |
| |
| doRequest('no cert proxy', { // invalid |
| maxSockets: 1, |
| ca: [serverCA], |
| rejectUnauthorized: true, |
| // client certification for origin server |
| key: client1Key, |
| cert: client1Cert, |
| proxy: { |
| port: proxyPort, |
| ca: [proxyCA], |
| rejectUnauthorized: true, |
| headers: { |
| host: 'proxy2' |
| } |
| // no certificate for proxy |
| } |
| }, 'server2'); |
| |
| doRequest('no cert origin', { // invalid |
| maxSockets: 1, |
| ca: [serverCA], |
| rejectUnauthorized: true, |
| // no certificate for origin server |
| proxy: { |
| port: proxyPort, |
| servername: 'proxy2', |
| ca: [proxyCA], |
| rejectUnauthorized: true, |
| headers: { |
| host: 'proxy2' |
| }, |
| // client certification for proxy |
| key: client2Key, |
| cert: client2Cert |
| } |
| }, 'server2'); |
| |
| doRequest('invalid proxy server name', { // invalid |
| maxSockets: 1, |
| ca: [serverCA], |
| rejectUnauthorized: true, |
| // client certification for origin server |
| key: client1Key, |
| cert: client1Cert, |
| proxy: { |
| port: proxyPort, |
| ca: [proxyCA], |
| rejectUnauthorized: true, |
| // client certification for proxy |
| key: client2Key, |
| cert: client2Cert, |
| } |
| }, 'server2'); |
| |
| doRequest('invalid origin server name', { // invalid |
| maxSockets: 1, |
| ca: [serverCA], |
| rejectUnauthorized: true, |
| // client certification for origin server |
| key: client1Key, |
| cert: client1Cert, |
| proxy: { |
| port: proxyPort, |
| servername: 'proxy2', |
| ca: [proxyCA], |
| rejectUnauthorized: true, |
| headers: { |
| host: 'proxy2' |
| }, |
| // client certification for proxy |
| key: client2Key, |
| cert: client2Cert |
| } |
| }); |
| |
| doRequest('valid', { // valid |
| maxSockets: 1, |
| ca: [serverCA], |
| rejectUnauthorized: true, |
| // client certification for origin server |
| key: client1Key, |
| cert: client1Cert, |
| proxy: { |
| port: proxyPort, |
| servername: 'proxy2', |
| ca: [proxyCA], |
| rejectUnauthorized: true, |
| headers: { |
| host: 'proxy2' |
| }, |
| // client certification for proxy |
| key: client2Key, |
| cert: client2Cert |
| } |
| }, 'server2'); |
| } |
| |
| server.on('close', function() { |
| serverConnect.should.equal(1); |
| proxyConnect.should.equal(3); |
| clientConnect.should.equal(1); |
| clientError.should.equal(5); |
| |
| done(); |
| }); |
| }); |
| }); |