mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
ssh commands: fix parsing commands with space
For now we support "\" escaping style
This commit is contained in:
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user