1
0
Fork 0
forked from svrjs/svrjs
This repository has been archived on 2024-11-10. You can view files and clone it, but cannot push or open issues or pull requests.
svrjs/tests/middleware/nonStandardCodesAndHttpAuthentication.test.js

281 lines
7.6 KiB
JavaScript

const sha256 = require("../../src/utils/sha256.js");
const ipMatch = require("../../src/utils/ipMatch.js");
const matchHostname = require("../../src/utils/matchHostname.js");
const ipBlockList = require("../../src/utils/ipBlockList.js");
const cluster = require("../../src/utils/clusterShim.js");
jest.mock("../../src/utils/sha256.js");
jest.mock("../../src/utils/ipMatch.js");
jest.mock("../../src/utils/matchHostname.js");
jest.mock("../../src/utils/ipBlockList.js");
jest.mock("../../src/utils/clusterShim.js");
let mockScryptHash = "mocked-scrypt-hash";
let mockPbkdf2Hash = "mocked-pbkdf2-hash";
jest.mock("crypto", () => {
return {
scrypt: jest.fn((password, salt, keylen, callback) => {
// Mock implementation for crypto.scrypt
callback(null, Buffer.from(mockScryptHash));
}),
pbkdf2: jest.fn((password, salt, iterations, keylen, digest, callback) => {
// Mock implementation for crypto.pbkdf2
callback(null, Buffer.from(mockPbkdf2Hash));
})
// Add other properties or methods of crypto module if needed
};
});
process.serverConfig = {
nonStandardCodes: [
{
host: "example.com",
ip: "192.168.1.1",
url: "/test/path",
scode: 403,
users: ["127.0.0.1"]
},
{
host: "example.com",
ip: "192.168.1.1",
url: "/test/path2",
scode: 401
}
]
};
process.messageEventListeners = [];
process.send = undefined;
const middleware = require("../../src/middleware/nonStandardCodesAndHttpAuthentication.js");
describe("Non-standard codes and HTTP authentication middleware", () => {
let req, res, logFacilities, config, next;
beforeEach(() => {
req = {
socket: {
realRemoteAddress: "127.0.0.1",
localAddress: "192.168.1.1"
},
parsedURL: {
pathname: "/test/path"
},
url: "/test/path",
headers: {
host: "example.com"
},
isProxy: false
};
res = {
error: jest.fn(),
redirect: jest.fn()
};
logFacilities = {
errmessage: jest.fn(),
reqmessage: jest.fn()
};
config = {
getCustomHeaders: jest.fn(),
users: []
};
next = jest.fn();
process.serverConfig = {
nonStandardCodes: []
};
cluster.isPrimary = true;
config.getCustomHeaders.mockReturnValue({});
});
test("should handle non-standard codes", () => {
ipBlockList.mockReturnValue({
check: jest.fn().mockReturnValue(true)
});
matchHostname.mockReturnValue(true);
ipMatch.mockReturnValue(true);
middleware(req, res, logFacilities, config, next);
expect(res.error).toHaveBeenCalledWith(403);
expect(logFacilities.errmessage).toHaveBeenCalledWith("Content blocked.");
});
test("should handle HTTP authentication", () => {
req.parsedURL.pathname = "/test/path2";
req.url = "/test/path2";
matchHostname.mockReturnValue(true);
ipMatch.mockReturnValue(true);
config.users = [
{
name: "test",
pass: "test",
salt: "test"
}
];
sha256.mockReturnValue("test");
req.headers.authorization = "Basic dGVzdDp0ZXN0";
middleware(req, res, logFacilities, config, next);
expect(next).toHaveBeenCalled();
expect(logFacilities.reqmessage).toHaveBeenCalledWith(
'Client is logged in as "test".'
);
});
test("should handle brute force protection", () => {
req.parsedURL.pathname = "/test/path2";
req.url = "/test/path2";
req.socket.realRemoteAddress = "127.0.0.2";
matchHostname.mockReturnValue(true);
ipMatch.mockReturnValue(true);
config.users = [
{
name: "test",
pass: "test2",
salt: "test"
}
];
sha256.mockReturnValue("test");
req.headers.authorization = "Basic dGVzdDp0ZXN0";
// Maximum 10 login attempts by default
for (let i = 0; i < 11; i++) {
logFacilities.errmessage.mockClear();
middleware(req, res, logFacilities, config, next);
}
expect(next).not.toHaveBeenCalled();
expect(logFacilities.errmessage).toHaveBeenCalledWith(
"Brute force limit reached!"
);
});
test("should handle HTTP authentication with scrypt", () => {
req.parsedURL.pathname = "/test/path2";
req.url = "/test/path2";
matchHostname.mockReturnValue(true);
ipMatch.mockReturnValue(true);
config.users = [
{
name: "test",
pass: "74657374", // "test" converted to hex
salt: "test",
scrypt: true
}
];
mockScryptHash = "test";
req.headers.authorization = "Basic dGVzdDp0ZXN0";
middleware(req, res, logFacilities, config, next);
expect(next).toHaveBeenCalled();
expect(logFacilities.reqmessage).toHaveBeenCalledWith(
'Client is logged in as "test".'
);
});
test("should handle HTTP authentication with PBKDF2", () => {
req.parsedURL.pathname = "/test/path2";
req.url = "/test/path2";
matchHostname.mockReturnValue(true);
ipMatch.mockReturnValue(true);
config.users = [
{
name: "test",
pass: "74657374", // "test" converted to hex
salt: "test",
pbkdf2: true
}
];
mockPbkdf2Hash = "test";
req.headers.authorization = "Basic dGVzdDp0ZXN0";
middleware(req, res, logFacilities, config, next);
expect(next).toHaveBeenCalled();
expect(logFacilities.reqmessage).toHaveBeenCalledWith(
'Client is logged in as "test".'
);
});
test("should call next if no non-standard codes or HTTP authentication is needed", () => {
req.parsedURL.pathname = "/test/path3";
req.url = "/test/path3";
middleware(req, res, logFacilities, config, next);
expect(next).toHaveBeenCalled();
});
test("should handle HTTP authentication with clustering", () => {
cluster.isPrimary = false;
req.parsedURL.pathname = "/test/path2";
req.url = "/test/path2";
matchHostname.mockReturnValue(true);
ipMatch.mockReturnValue(true);
config.users = [
{
name: "test",
pass: "test",
salt: "test"
}
];
sha256.mockReturnValue("test");
req.headers.authorization = "Basic dGVzdDp0ZXN0";
let mockHandlers = [];
process.on = (eventType, eventListener) => {
if (eventType == "message") {
mockHandlers.push(eventListener);
}
};
process.once = (eventType, eventListener) => {
const wrap = (...params) => {
eventListener(...params);
process.removeListener(eventType, wrap);
};
process.on(eventType, wrap);
};
process.addListener = process.on;
process.removeListener = (eventType, eventListener) => {
if (eventType == "message") {
let indexOfListener = mockHandlers.indexOf(eventListener);
if (indexOfListener != -1) mockHandlers.splice(indexOfListener, 1);
}
};
process.removeAllListeners = (eventType) => {
if (eventType == "message") {
mockHandlers = [];
}
};
process.send = (message) => {
const mockWorker = {
send: (msg) => {
mockHandlers.forEach((handler) => handler(msg));
}
};
const mockServerConsole = {
climessage: () => {},
reqmessage: () => {},
resmessage: () => {},
errmessage: () => {},
locerrmessage: () => {},
locwarnmessage: () => {},
locmessage: () => {}
};
process.messageEventListeners.forEach((listenerWrapper) =>
listenerWrapper(mockWorker, mockServerConsole)(message)
);
};
middleware(req, res, logFacilities, config, next);
expect(next).toHaveBeenCalled();
expect(logFacilities.reqmessage).toHaveBeenCalledWith(
'Client is logged in as "test".'
);
});
});