mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-03-03 05:55:03 +01:00
129 lines
5.1 KiB
TypeScript
129 lines
5.1 KiB
TypeScript
import fs from 'fs';
|
|
import net, { Socket } from 'net';
|
|
import path from 'path';
|
|
import util from 'util';
|
|
|
|
import { TorControlPort, createHmacSignature, getCookieString } from '../src/torControlPort';
|
|
import type { TorConnectionOptions } from '../src/types';
|
|
|
|
const writeFile = util.promisify(fs.writeFile);
|
|
const existsDirectory = util.promisify(fs.exists);
|
|
const mkdir = util.promisify(fs.mkdir);
|
|
const unlinkFile = util.promisify(fs.unlink);
|
|
|
|
const torDataDir = path.join(__dirname, 'tmp');
|
|
// Because control_auth_cookie is shared by other tests, this test should not run in parallel
|
|
// using `--runInBand` option with jest.
|
|
const controlAuthCookiePath = `${torDataDir}/control_auth_cookie`;
|
|
const host = 'localhost';
|
|
const port = 9998;
|
|
const controlPort = 9999;
|
|
|
|
// TODO: Skipping this for now, since I want to get the most critical tests to run in CI.
|
|
describe.skip('TorControlPort', () => {
|
|
beforeAll(async () => {
|
|
if (!(await existsDirectory(torDataDir))) {
|
|
// Make sure there is `torDataDir` directory.
|
|
mkdir(torDataDir);
|
|
}
|
|
await writeFile(controlAuthCookiePath, 'test');
|
|
});
|
|
|
|
afterAll(async () => {
|
|
await unlinkFile(controlAuthCookiePath);
|
|
});
|
|
|
|
describe('TorControlPort is not connected', () => {
|
|
it('TorControlPort ping should return false when TOR is not running', () => {
|
|
const options: TorConnectionOptions = {
|
|
host,
|
|
port,
|
|
controlPort,
|
|
torDataDir,
|
|
};
|
|
const fakeListener = () => {};
|
|
const torControlPort = new TorControlPort(options, fakeListener);
|
|
const pingResponse = torControlPort.ping();
|
|
expect(pingResponse).toEqual(false);
|
|
});
|
|
});
|
|
|
|
describe('TorControlPort should authorize when connecting', () => {
|
|
it('Tor control port connects', async () => {
|
|
let isProperlyAuthenticated = false;
|
|
const serverHash = '1A6C3485BD58CAF688C5AF98B878E713A6EF0EAC0240D7E3453341689BA7FC60';
|
|
const serverNonce = '88601906AB5EB92B8CB86E012C0074855E23AA1C79F843BEA5FDE674936E9AB1';
|
|
const cookieString = await getCookieString(torDataDir);
|
|
const authenticationKey = 'Tor safe cookie authentication controller-to-server hash';
|
|
|
|
let clientNonce = '';
|
|
|
|
function torControlPortMock(sock: Socket) {
|
|
sock.on('data', (data: string) => {
|
|
const message = data.toString();
|
|
|
|
const authchallengeRequest = message
|
|
.trim()
|
|
.match(/^AUTHCHALLENGE SAFECOOKIE ([a-fA-F0-9]+)$/m);
|
|
const authenticateRequest = message
|
|
.trim()
|
|
.match(/^AUTHENTICATE ([a-fA-F0-9]+)$/m);
|
|
const providedAuthSignature = authenticateRequest && authenticateRequest[1];
|
|
|
|
const authString = `${cookieString}${clientNonce}${serverNonce}`;
|
|
const authSignature = createHmacSignature(authString, authenticationKey);
|
|
|
|
switch (true) {
|
|
case !!authenticateRequest:
|
|
isProperlyAuthenticated = providedAuthSignature === authSignature;
|
|
sock.write('250 OK');
|
|
break;
|
|
case !!authchallengeRequest:
|
|
clientNonce = authchallengeRequest ? authchallengeRequest[1] : '';
|
|
sock.write(
|
|
`250 AUTHCHALLENGE SERVERHASH=${serverHash} SERVERNONCE=${serverNonce}`,
|
|
);
|
|
break;
|
|
default:
|
|
}
|
|
});
|
|
}
|
|
|
|
const serverControlPort = net.createServer(torControlPortMock);
|
|
const startListening = () =>
|
|
new Promise(resolve => {
|
|
serverControlPort.listen(controlPort, host, () => {
|
|
resolve(1);
|
|
});
|
|
});
|
|
|
|
await startListening();
|
|
|
|
const options: TorConnectionOptions = {
|
|
host,
|
|
port,
|
|
controlPort,
|
|
torDataDir,
|
|
};
|
|
const fakeListener = () => {};
|
|
const torControlPort = new TorControlPort(options, fakeListener);
|
|
await torControlPort.connect();
|
|
const response = torControlPort.ping();
|
|
expect(response).toEqual(true);
|
|
const waitForProperAuth = () =>
|
|
new Promise(resolve => {
|
|
const interval = setInterval(() => {
|
|
if (isProperlyAuthenticated) {
|
|
clearInterval(interval);
|
|
resolve(isProperlyAuthenticated);
|
|
}
|
|
}, 100);
|
|
});
|
|
expect(await waitForProperAuth()).toEqual(true);
|
|
|
|
serverControlPort.close();
|
|
torControlPort.socket.destroy();
|
|
});
|
|
});
|
|
});
|