* Disconnect clients that attempt to login with banned usernames for Telnet as well
* Slow disconnects to thwart brute force attacks - these names won't exist anyway, but we want the attacking client to not DoS us
This commit is contained in:
parent
06a1925288
commit
ee93035bb8
|
@ -25,6 +25,7 @@ This document attempts to track **major** changes and additions in ENiGMA½. For
|
||||||
* NNTP support! See [NNTP docs](/docs/servers/nntp.md) for more information.
|
* NNTP support! See [NNTP docs](/docs/servers/nntp.md) for more information.
|
||||||
* `oputil.js user rm` and `oputil.js user info` are in! See [oputil CLI](/docs/admin/oputil.md).
|
* `oputil.js user rm` and `oputil.js user info` are in! See [oputil CLI](/docs/admin/oputil.md).
|
||||||
* Performing a file scan/import using `oputil.js fb scan` now recognizes various `FILES.BBS` formats.
|
* Performing a file scan/import using `oputil.js fb scan` now recognizes various `FILES.BBS` formats.
|
||||||
|
* Usernames found in the `config.users.badUserNames` are now not only disallowed from applying, but disconnected at any login attempt.
|
||||||
|
|
||||||
|
|
||||||
## 0.0.8-alpha
|
## 0.0.8-alpha
|
||||||
|
|
|
@ -57,39 +57,46 @@ function SSHClient(clientConn) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function terminateConnection() {
|
const terminateConnection = () => {
|
||||||
safeContextReject();
|
safeContextReject();
|
||||||
return clientConn.end();
|
return clientConn.end();
|
||||||
}
|
};
|
||||||
|
|
||||||
function promptAndTerm(msg) {
|
// slow version to thwart brute force attacks
|
||||||
|
const slowTerminateConnection = () => {
|
||||||
|
setTimeout( () => {
|
||||||
|
return terminateConnection();
|
||||||
|
}, 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const promptAndTerm = (msg, method = 'standard') => {
|
||||||
if('keyboard-interactive' === ctx.method) {
|
if('keyboard-interactive' === ctx.method) {
|
||||||
ctx.prompt(msg);
|
ctx.prompt(msg);
|
||||||
}
|
}
|
||||||
return terminateConnection();
|
return 'slow' === method ? slowTerminateConnection() : terminateConnection();
|
||||||
}
|
};
|
||||||
|
|
||||||
function accountAlreadyLoggedIn(username) {
|
const accountAlreadyLoggedIn = (username) => {
|
||||||
return promptAndTerm(`${username} is already connected to the system. Terminating connection.\n(Press any key to continue)`);
|
return promptAndTerm(`${username} is already connected to the system. Terminating connection.\n(Press any key to continue)`);
|
||||||
}
|
};
|
||||||
|
|
||||||
function accountDisabled(username) {
|
const accountDisabled = (username) => {
|
||||||
return promptAndTerm(`${username} is disabled.\n(Press any key to continue)`);
|
return promptAndTerm(`${username} is disabled.\n(Press any key to continue)`);
|
||||||
}
|
};
|
||||||
|
|
||||||
function accountInactive(username) {
|
const accountInactive = (username) => {
|
||||||
return promptAndTerm(`${username} is waiting for +op activation.\n(Press any key to continue)`);
|
return promptAndTerm(`${username} is waiting for +op activation.\n(Press any key to continue)`);
|
||||||
}
|
};
|
||||||
|
|
||||||
function accountLocked(username) {
|
const accountLocked = (username) => {
|
||||||
return promptAndTerm(`${username} is locked.\n(Press any key to continue)`);
|
return promptAndTerm(`${username} is locked.\n(Press any key to continue)`, 'slow');
|
||||||
}
|
};
|
||||||
|
|
||||||
function isSpecialHandleError(err) {
|
const isSpecialHandleError = (err) => {
|
||||||
return [ ErrorReasons.AlreadyLoggedIn, ErrorReasons.Disabled, ErrorReasons.Inactive, ErrorReasons.Locked ].includes(err.reasonCode);
|
return [ ErrorReasons.AlreadyLoggedIn, ErrorReasons.Disabled, ErrorReasons.Inactive, ErrorReasons.Locked ].includes(err.reasonCode);
|
||||||
}
|
};
|
||||||
|
|
||||||
function handleSpecialError(err, username) {
|
const handleSpecialError = (err, username) => {
|
||||||
switch(err.reasonCode) {
|
switch(err.reasonCode) {
|
||||||
case ErrorReasons.AlreadyLoggedIn : return accountAlreadyLoggedIn(username);
|
case ErrorReasons.AlreadyLoggedIn : return accountAlreadyLoggedIn(username);
|
||||||
case ErrorReasons.Inactive : return accountInactive(username);
|
case ErrorReasons.Inactive : return accountInactive(username);
|
||||||
|
@ -97,7 +104,7 @@ function SSHClient(clientConn) {
|
||||||
case ErrorReasons.Locked : return accountLocked(username);
|
case ErrorReasons.Locked : return accountLocked(username);
|
||||||
default : return terminateConnection();
|
default : return terminateConnection();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// If the system is open and |isNewUser| is true, the login
|
// If the system is open and |isNewUser| is true, the login
|
||||||
|
@ -115,7 +122,7 @@ function SSHClient(clientConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Errors.BadLogin().code === err.code) {
|
if(Errors.BadLogin().code === err.code) {
|
||||||
return terminateConnection();
|
return slowTerminateConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
return safeContextReject(SSHClient.ValidAuthMethods);
|
return safeContextReject(SSHClient.ValidAuthMethods);
|
||||||
|
@ -143,7 +150,7 @@ function SSHClient(clientConn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Errors.BadLogin().code === err.code) {
|
if(Errors.BadLogin().code === err.code) {
|
||||||
return terminateConnection();
|
return slowTerminateConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
const artOpts = {
|
const artOpts = {
|
||||||
|
|
|
@ -34,6 +34,11 @@ function login(callingMenu, formData, extraArgs, cb) {
|
||||||
return callingMenu.gotoMenu(callingMenu.menuConfig.config.tooNodeMenu, cb);
|
return callingMenu.gotoMenu(callingMenu.menuConfig.config.tooNodeMenu, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// banned username results in disconnect
|
||||||
|
if(ErrorReasons.NotAllowed === err.reasonCode) {
|
||||||
|
return logoff(callingMenu, {}, {}, cb);
|
||||||
|
}
|
||||||
|
|
||||||
const ReasonsMenus = [
|
const ReasonsMenus = [
|
||||||
ErrorReasons.TooMany, ErrorReasons.Disabled, ErrorReasons.Inactive, ErrorReasons.Locked
|
ErrorReasons.TooMany, ErrorReasons.Disabled, ErrorReasons.Inactive, ErrorReasons.Locked
|
||||||
];
|
];
|
||||||
|
|
|
@ -27,7 +27,11 @@ function userLogin(client, username, password, cb) {
|
||||||
|
|
||||||
if(config.users.badUserNames.includes(username.toLowerCase())) {
|
if(config.users.badUserNames.includes(username.toLowerCase())) {
|
||||||
client.log.info( { username : username }, 'Attempt to login with banned username');
|
client.log.info( { username : username }, 'Attempt to login with banned username');
|
||||||
return cb(Errors.BadLogin(ErrorReasons.NotAllowed));
|
|
||||||
|
// slow down a bit to thwart brute force attacks
|
||||||
|
return setTimeout( () => {
|
||||||
|
return cb(Errors.BadLogin('Disallowed username', ErrorReasons.NotAllowed));
|
||||||
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
client.user.authenticate(username, password, err => {
|
client.user.authenticate(username, password, err => {
|
||||||
|
|
Loading…
Reference in New Issue