ssh commands: fix parsing commands with space

For now we support "\" escaping style
This commit is contained in:
Nicola Murino
2020-02-08 23:33:06 +01:00
parent d6fa853a37
commit 7bfe0ddf80
4 changed files with 32 additions and 4 deletions

View File

@@ -301,7 +301,7 @@ sftpgo initprovider --help
The `initprovider` command is enough for new installations. From now on, the database structure will be automatically checked and updated, if required, at startup. The `initprovider` command is enough for new installations. From now on, the database structure will be automatically checked and updated, if required, at startup.
If you are upgrading from version 0.9.5 or before you have to manually execute the SQL scripts to create the required database structure.Theese script can be found inside the source tree [sql](./sql "sql") directory. The SQL scripts filename is, by convention, the date as `YYYYMMDD` and the suffix `.sql`. You need to apply all the SQL scripts for your database ordered by name, for example `20190828.sql` must be applied before `20191112.sql` and so on. If you are upgrading from version 0.9.5 or before you have to manually execute the SQL scripts to create the required database structure.These script can be found inside the source tree [sql](./sql "sql") directory. The SQL scripts filename is, by convention, the date as `YYYYMMDD` and the suffix `.sql`. You need to apply all the SQL scripts for your database ordered by name, for example `20190828.sql` must be applied before `20191112.sql` and so on.
Example for SQLite: `find sql/sqlite/ -type f -iname '*.sql' -print | sort -n | xargs cat | sqlite3 sftpgo.db`. Example for SQLite: `find sql/sqlite/ -type f -iname '*.sql' -print | sort -n | xargs cat | sqlite3 sftpgo.db`.
After applying these scripts your database structure is the same as the one obtained using `initprovider` for new installations, so from now on you don't have to manually upgrade your database anymore. After applying these scripts your database structure is the same as the one obtained using `initprovider` for new installations, so from now on you don't have to manually upgrade your database anymore.

View File

@@ -628,6 +628,25 @@ func TestSSHCommandPath(t *testing.T) {
if path != "/" { if path != "/" {
t.Errorf("unexpected path: %v", path) t.Errorf("unexpected path: %v", path)
} }
sshCommand.args = []string{"-f", "/a space.txt"}
path = sshCommand.getDestPath()
if path != "/a space.txt" {
t.Errorf("unexpected path: %v", path)
}
}
func TestSSHParseCommandPayload(t *testing.T) {
cmd := "command -a -f some\\ spaces\\ \\ .txt"
name, args, _ := parseCommandPayload(cmd)
if name != "command" {
t.Errorf("unexpected command: %v", name)
}
if len(args) != 3 {
t.Errorf("unexpected number of arguments %v/3", len(args))
}
if !utils.IsStringInSlice("some spaces .txt", args) {
t.Errorf("command parsing error, expected arguments not found: %v", args)
}
} }
func TestSSHCommandErrors(t *testing.T) { func TestSSHCommandErrors(t *testing.T) {

View File

@@ -56,6 +56,7 @@ func (c *scpCommand) handle() error {
} }
} else { } else {
err = fmt.Errorf("scp command not supported, args: %v", c.args) err = fmt.Errorf("scp command not supported, args: %v", c.args)
c.connection.Log(logger.LevelDebug, logSenderSCP, "unsupported scp command, args: %v", c.args)
} }
c.sendExitStatus(err) c.sendExitStatus(err)
return err return err

View File

@@ -45,7 +45,7 @@ type systemCommand struct {
func processSSHCommand(payload []byte, connection *Connection, channel ssh.Channel, enabledSSHCommands []string) bool { func processSSHCommand(payload []byte, connection *Connection, channel ssh.Channel, enabledSSHCommands []string) bool {
var msg sshSubsystemExecMsg var msg sshSubsystemExecMsg
if err := ssh.Unmarshal(payload, &msg); err == nil { if err := ssh.Unmarshal(payload, &msg); err == nil {
name, args, err := parseCommandPayload(msg.Command) name, args, err := parseCommandPayload(strings.TrimSpace(msg.Command))
connection.Log(logger.LevelDebug, logSenderSSH, "new ssh command: %#v args: %v user: %v, error: %v", connection.Log(logger.LevelDebug, logSenderSSH, "new ssh command: %#v args: %v user: %v, error: %v",
name, args, connection.User.Username, err) name, args, connection.User.Username, err)
if err == nil && utils.IsStringInSlice(name, enabledSSHCommands) { if err == nil && utils.IsStringInSlice(name, enabledSSHCommands) {
@@ -421,9 +421,17 @@ func computeHashForFile(hasher hash.Hash, path string) (string, error) {
} }
func parseCommandPayload(command string) (string, []string, error) { func parseCommandPayload(command string) (string, []string, error) {
parts := strings.Split(command, " ") parts := strings.Split(strings.ReplaceAll(command, "\\ ", "\\"), " ")
if len(parts) < 2 { if len(parts) < 2 {
return parts[0], []string{}, nil return parts[0], []string{}, nil
} }
return parts[0], parts[1:], nil args := []string{}
for _, arg := range parts[1:] {
parsed := strings.TrimSpace(strings.ReplaceAll(arg, "\\", " "))
if len(parsed) == 0 {
continue
}
args = append(args, parsed)
}
return parts[0], args, nil
} }