1 | var http = require('http');
|
2 | var https = require('https');
|
3 | var net = require('net');
|
4 | var fs = require('fs');
|
5 | var path = require('path');
|
6 | var should = require('should');
|
7 | var tunnel = require('../index');
|
8 |
|
9 | function readPem(file) {
|
10 | return fs.readFileSync(path.join('test/keys', file + '.pem'));
|
11 | }
|
12 |
|
13 | var serverKey = readPem('server2-key');
|
14 | var serverCert = readPem('server2-cert');
|
15 | var serverCA = readPem('ca1-cert');
|
16 | var proxyKey = readPem('proxy2-key');
|
17 | var proxyCert = readPem('proxy2-cert');
|
18 | var proxyCA = readPem('ca2-cert');
|
19 | var client1Key = readPem('client1-key');
|
20 | var client1Cert = readPem('client1-cert');
|
21 | var client1CA = readPem('ca3-cert');
|
22 | var client2Key = readPem('client2-key');
|
23 | var client2Cert = readPem('client2-cert');
|
24 | var client2CA = readPem('ca4-cert');
|
25 |
|
26 | describe('HTTPS over HTTPS authentication failed', function() {
|
27 | it('should finish without error', function(done) {
|
28 | var serverPort = 3008;
|
29 | var proxyPort = 3009;
|
30 | var serverConnect = 0;
|
31 | var proxyConnect = 0;
|
32 | var clientRequest = 0;
|
33 | var clientConnect = 0;
|
34 | var clientError = 0;
|
35 | var server;
|
36 | var proxy;
|
37 |
|
38 | server = https.createServer({
|
39 | key: serverKey,
|
40 | cert: serverCert,
|
41 | ca: [client1CA],
|
42 | requestCert: true,
|
43 | rejectUnauthorized: true
|
44 | }, function(req, res) {
|
45 | tunnel.debug('SERVER: got request', req.url);
|
46 | ++serverConnect;
|
47 | req.on('data', function(data) {
|
48 | });
|
49 | req.on('end', function() {
|
50 | res.writeHead(200);
|
51 | res.end('Hello, ' + serverConnect);
|
52 | tunnel.debug('SERVER: sending response');
|
53 | });
|
54 | req.resume();
|
55 | });
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 | server.listen(serverPort, setupProxy);
|
62 |
|
63 | function setupProxy() {
|
64 | proxy = https.createServer({
|
65 | key: proxyKey,
|
66 | cert: proxyCert,
|
67 | ca: [client2CA],
|
68 | requestCert: true,
|
69 | rejectUnauthorized: true
|
70 | }, function(req, res) {
|
71 | should.fail();
|
72 | });
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 | proxy.on('upgrade', onConnect);
|
79 | proxy.on('connect', onConnect);
|
80 |
|
81 | function onConnect(req, clientSocket, head) {
|
82 | req.method.should.equal('CONNECT');
|
83 | req.url.should.equal('localhost:' + serverPort);
|
84 | req.headers.should.not.have.property('transfer-encoding');
|
85 | ++proxyConnect;
|
86 |
|
87 | var serverSocket = net.connect(serverPort, function() {
|
88 | tunnel.debug('PROXY: replying to client CONNECT request');
|
89 | clientSocket.write('HTTP/1.1 200 Connection established\r\n\r\n');
|
90 | clientSocket.pipe(serverSocket);
|
91 | serverSocket.write(head);
|
92 | serverSocket.pipe(clientSocket);
|
93 |
|
94 | serverSocket.on('end', function() {
|
95 | clientSocket.end();
|
96 | });
|
97 | });
|
98 | }
|
99 | proxy.listen(proxyPort, setupClient);
|
100 | }
|
101 |
|
102 | function setupClient() {
|
103 | function doRequest(name, options, host) {
|
104 | tunnel.debug('CLIENT: Making HTTPS request (%s)', name);
|
105 | ++clientRequest;
|
106 | var agent = tunnel.httpsOverHttps(options);
|
107 | var req = https.get({
|
108 | host: 'localhost',
|
109 | port: serverPort,
|
110 | path: '/' + encodeURIComponent(name),
|
111 | headers: {
|
112 | host: host ? host : 'localhost',
|
113 | },
|
114 | rejectUnauthorized: true,
|
115 | agent: agent
|
116 | }, function(res) {
|
117 | tunnel.debug('CLIENT: got HTTPS response (%s)', name);
|
118 | ++clientConnect;
|
119 | res.on('data', function(data) {
|
120 | });
|
121 | res.on('end', function() {
|
122 | req.emit('finish');
|
123 | });
|
124 | res.resume();
|
125 | });
|
126 | req.on('error', function(err) {
|
127 | tunnel.debug('CLIENT: failed HTTP response (%s)', name, err);
|
128 | ++clientError;
|
129 | req.emit('finish');
|
130 | });
|
131 | req.on('finish', function() {
|
132 | if (clientConnect + clientError === clientRequest) {
|
133 | proxy.close();
|
134 | server.close();
|
135 | }
|
136 | });
|
137 | }
|
138 |
|
139 | doRequest('no cert origin nor proxy', {
|
140 | maxSockets: 1,
|
141 | ca: [serverCA],
|
142 | rejectUnauthorized: true,
|
143 |
|
144 | proxy: {
|
145 | port: proxyPort,
|
146 | ca: [proxyCA],
|
147 | rejectUnauthorized: true,
|
148 | headers: {
|
149 | host: 'proxy2'
|
150 | }
|
151 |
|
152 | }
|
153 | }, 'server2');
|
154 |
|
155 | doRequest('no cert proxy', {
|
156 | maxSockets: 1,
|
157 | ca: [serverCA],
|
158 | rejectUnauthorized: true,
|
159 |
|
160 | key: client1Key,
|
161 | cert: client1Cert,
|
162 | proxy: {
|
163 | port: proxyPort,
|
164 | ca: [proxyCA],
|
165 | rejectUnauthorized: true,
|
166 | headers: {
|
167 | host: 'proxy2'
|
168 | }
|
169 |
|
170 | }
|
171 | }, 'server2');
|
172 |
|
173 | doRequest('no cert origin', {
|
174 | maxSockets: 1,
|
175 | ca: [serverCA],
|
176 | rejectUnauthorized: true,
|
177 |
|
178 | proxy: {
|
179 | port: proxyPort,
|
180 | servername: 'proxy2',
|
181 | ca: [proxyCA],
|
182 | rejectUnauthorized: true,
|
183 | headers: {
|
184 | host: 'proxy2'
|
185 | },
|
186 |
|
187 | key: client2Key,
|
188 | cert: client2Cert
|
189 | }
|
190 | }, 'server2');
|
191 |
|
192 | doRequest('invalid proxy server name', {
|
193 | maxSockets: 1,
|
194 | ca: [serverCA],
|
195 | rejectUnauthorized: true,
|
196 |
|
197 | key: client1Key,
|
198 | cert: client1Cert,
|
199 | proxy: {
|
200 | port: proxyPort,
|
201 | ca: [proxyCA],
|
202 | rejectUnauthorized: true,
|
203 |
|
204 | key: client2Key,
|
205 | cert: client2Cert,
|
206 | }
|
207 | }, 'server2');
|
208 |
|
209 | doRequest('invalid origin server name', {
|
210 | maxSockets: 1,
|
211 | ca: [serverCA],
|
212 | rejectUnauthorized: true,
|
213 |
|
214 | key: client1Key,
|
215 | cert: client1Cert,
|
216 | proxy: {
|
217 | port: proxyPort,
|
218 | servername: 'proxy2',
|
219 | ca: [proxyCA],
|
220 | rejectUnauthorized: true,
|
221 | headers: {
|
222 | host: 'proxy2'
|
223 | },
|
224 |
|
225 | key: client2Key,
|
226 | cert: client2Cert
|
227 | }
|
228 | });
|
229 |
|
230 | doRequest('valid', {
|
231 | maxSockets: 1,
|
232 | ca: [serverCA],
|
233 | rejectUnauthorized: true,
|
234 |
|
235 | key: client1Key,
|
236 | cert: client1Cert,
|
237 | proxy: {
|
238 | port: proxyPort,
|
239 | servername: 'proxy2',
|
240 | ca: [proxyCA],
|
241 | rejectUnauthorized: true,
|
242 | headers: {
|
243 | host: 'proxy2'
|
244 | },
|
245 |
|
246 | key: client2Key,
|
247 | cert: client2Cert
|
248 | }
|
249 | }, 'server2');
|
250 | }
|
251 |
|
252 | server.on('close', function() {
|
253 | serverConnect.should.equal(1);
|
254 | proxyConnect.should.equal(3);
|
255 | clientConnect.should.equal(1);
|
256 | clientError.should.equal(5);
|
257 |
|
258 | done();
|
259 | });
|
260 | });
|
261 | });
|