feat: add black/white list for commands

Allow black/white list to be set for individual connections

BREAKING CHANGE: name change, removed `disabled_commands`
This commit is contained in:
Tyler Stewart
2017-03-07 18:39:39 -07:00
parent e5b10c5858
commit f6d1a3828a
4 changed files with 22 additions and 8 deletions

View File

@@ -50,10 +50,14 @@ __anonymous__ : `false`
> Set whether a valid username or password combination is required.
If true, will not require the `PASS` command to be sent for login.
__disabled_commands__ : `[]`
> String array of commands to forbid.
__blacklist__ : `[]`
> Commands listed will not be allowed.
`['RMD', 'RNFR', 'RNTO']`
__whitelist__ : `[]`
> If set, no other commands are allowed except for those explicitly listed.
`['USER', 'PASS', 'PWD']`
__file_format__ : `ls`
> Format to use for [file stat](https://nodejs.org/api/fs.html#fs_class_fs_stats) responses (such as with the `LIST` command).
Possible values:
@@ -73,7 +77,9 @@ __login__ : `{connection, username, password}`
```
resolve({
fs, // [optional] custom file system class
cwd // [optional] initial working directory (if not using custom file system)
cwd, // [optional] initial working directory (if not using custom file system),
blacklist, // [optional] commands to forbid for this connection only
whitelist // [optional] if set, only these commands are allowed for this connection only
})
```

View File

@@ -6,7 +6,8 @@ class FtpCommands {
this.connection = connection;
this.registry = require('./registry');
this.previousCommand = {};
this.disabledCommands = _.get(this.connection, 'server.options.disabled_commands', []).map(cmd => _.upperCase(cmd));
this.blacklist = _.get(this.connection, 'server.options.blacklist', []).map(cmd => _.upperCase(cmd));
this.whitelist = _.get(this.connection, 'server.options.whitelist', []).map(cmd => _.upperCase(cmd));
}
handle(command) {
@@ -17,8 +18,12 @@ class FtpCommands {
return this.connection.reply(402, 'Command not allowed');
}
if (_.includes(this.disabledCommands, command.directive)) {
return this.connection.reply(502, 'Command forbidden');
if (_.includes(this.blacklist, command.directive)) {
return this.connection.reply(502, 'Command blacklisted');
}
if (this.whitelist.length > 0 && !_.includes(this.whitelist, command.directive)) {
return this.connection.reply(502, 'Command not whitelisted');
}
const commandRegister = this.registry[command.directive];

View File

@@ -62,8 +62,10 @@ class FtpConnection {
return this.server.emit('login', {connection: this, username, password});
}
})
.then(({fs, cwd} = {}) => {
.then(({fs, cwd, blacklist = [], whitelist = []} = {}) => {
this.authenticated = true;
this.commands.blacklist = _.concat(this.commands.blacklist, blacklist);
this.commands.whitelist = _.concat(this.commands.whitelist, whitelist);
this.fs = fs || new FileSystem(this, {cwd});
});
}

View File

@@ -14,7 +14,8 @@ class FtpServer {
anonymous: false,
pasv_range: 22,
file_format: 'ls',
disabled_commands: []
blacklist: [],
whitelist: []
}, options);
this.connections = {};