windows: try to escape trailing double quote in user input

we try to remove the trailing double quote for user input such as this one

sftpgo.exe serve -c "C:\ProgramData\SFTPGO\"

the value for the -c flag is parsed as:

C:\ProgramData\SFTPGO"

this is what the user specified, but the user want this value:

C:\ProgramData\SFTPGO

so we try to remove the trailing double quote.

Please note that we cannot do anything for something like this:

-c "C:\ProgramData\SFTPGO\" -l "sftpgo.log"

in this case the -l flag will be ignored and the value for the c flag is:

C:\ProgramData\SFTPGO" -l sftpgo.log

and so probably it is invalid. This is definitely a bad user input
This commit is contained in:
Nicola Murino
2020-03-04 09:27:14 +01:00
parent f9fc5792fd
commit 31d285813e
8 changed files with 29 additions and 18 deletions

View File

@@ -1,11 +1,10 @@
package cmd package cmd
import ( import (
"path/filepath"
"github.com/drakkan/sftpgo/config" "github.com/drakkan/sftpgo/config"
"github.com/drakkan/sftpgo/dataprovider" "github.com/drakkan/sftpgo/dataprovider"
"github.com/drakkan/sftpgo/logger" "github.com/drakkan/sftpgo/logger"
"github.com/drakkan/sftpgo/utils"
"github.com/rs/zerolog" "github.com/rs/zerolog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
@@ -31,7 +30,7 @@ Please take a look at the usage below to customize the options.`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
logger.DisableLogger() logger.DisableLogger()
logger.EnableConsoleLogger(zerolog.DebugLevel) logger.EnableConsoleLogger(zerolog.DebugLevel)
configDir = filepath.Clean(configDir) configDir = utils.CleanDirInput(configDir)
config.LoadConfig(configDir, configFile) config.LoadConfig(configDir, configFile)
providerConf := config.GetProviderConf() providerConf := config.GetProviderConf()
logger.DebugToConsole("Initializing provider: %#v config file: %#v", providerConf.Driver, viper.ConfigFileUsed()) logger.DebugToConsole("Initializing provider: %#v config file: %#v", providerConf.Driver, viper.ConfigFileUsed())

View File

@@ -2,9 +2,9 @@ package cmd
import ( import (
"fmt" "fmt"
"path/filepath"
"github.com/drakkan/sftpgo/service" "github.com/drakkan/sftpgo/service"
"github.com/drakkan/sftpgo/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -19,7 +19,7 @@ sftpgo service install
Please take a look at the usage below to customize the startup options`, Please take a look at the usage below to customize the startup options`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
s := service.Service{ s := service.Service{
ConfigDir: filepath.Clean(configDir), ConfigDir: utils.CleanDirInput(configDir),
ConfigFile: configFile, ConfigFile: configFile,
LogFilePath: logFilePath, LogFilePath: logFilePath,
LogMaxSize: logMaxSize, LogMaxSize: logMaxSize,

View File

@@ -138,7 +138,7 @@ func init() {
portableCmd.Flags().BoolVarP(&portableAdvertiseService, "advertise-service", "S", true, portableCmd.Flags().BoolVarP(&portableAdvertiseService, "advertise-service", "S", true,
"Advertise SFTP service using multicast DNS") "Advertise SFTP service using multicast DNS")
portableCmd.Flags().BoolVarP(&portableAdvertiseCredentials, "advertise-credentials", "C", false, portableCmd.Flags().BoolVarP(&portableAdvertiseCredentials, "advertise-credentials", "C", false,
"If the SFTP service is advertised via multicast DNS this flag allows to put username/password inside the advertised TXT record") "If the SFTP service is advertised via multicast DNS, this flag allows to put username/password inside the advertised TXT record")
portableCmd.Flags().IntVarP(&portableFsProvider, "fs-provider", "f", 0, "0 means local filesystem, 1 Amazon S3 compatible, "+ portableCmd.Flags().IntVarP(&portableFsProvider, "fs-provider", "f", 0, "0 means local filesystem, 1 Amazon S3 compatible, "+
"2 Google Cloud Storage") "2 Google Cloud Storage")
portableCmd.Flags().StringVar(&portableS3Bucket, "s3-bucket", "", "") portableCmd.Flags().StringVar(&portableS3Bucket, "s3-bucket", "", "")

View File

@@ -4,7 +4,6 @@ package cmd
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"strconv" "strconv"
"github.com/drakkan/sftpgo/config" "github.com/drakkan/sftpgo/config"
@@ -141,7 +140,7 @@ func addServeFlags(cmd *cobra.Command) {
func getCustomServeFlags() []string { func getCustomServeFlags() []string {
result := []string{} result := []string{}
if configDir != defaultConfigDir { if configDir != defaultConfigDir {
configDir = filepath.Clean(configDir) configDir = utils.CleanDirInput(configDir)
result = append(result, "--"+configDirFlag) result = append(result, "--"+configDirFlag)
result = append(result, configDir) result = append(result, configDir)
} }
@@ -149,10 +148,7 @@ func getCustomServeFlags() []string {
result = append(result, "--"+configFileFlag) result = append(result, "--"+configFileFlag)
result = append(result, configFile) result = append(result, configFile)
} }
if logFilePath != defaultLogFile && utils.IsFileInputValid(logFilePath) { if logFilePath != defaultLogFile {
if !filepath.IsAbs(logFilePath) {
logFilePath = filepath.Join(configDir, logFilePath)
}
result = append(result, "--"+logFilePathFlag) result = append(result, "--"+logFilePathFlag)
result = append(result, logFilePath) result = append(result, logFilePath)
} }

View File

@@ -1,9 +1,8 @@
package cmd package cmd
import ( import (
"path/filepath"
"github.com/drakkan/sftpgo/service" "github.com/drakkan/sftpgo/service"
"github.com/drakkan/sftpgo/utils"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@@ -18,7 +17,7 @@ sftpgo serve
Please take a look at the usage below to customize the startup options`, Please take a look at the usage below to customize the startup options`,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
service := service.Service{ service := service.Service{
ConfigDir: filepath.Clean(configDir), ConfigDir: utils.CleanDirInput(configDir),
ConfigFile: configFile, ConfigFile: configFile,
LogFilePath: logFilePath, LogFilePath: logFilePath,
LogMaxSize: logMaxSize, LogMaxSize: logMaxSize,

View File

@@ -14,7 +14,7 @@ var (
Use: "start", Use: "start",
Short: "Start SFTPGo Windows Service", Short: "Start SFTPGo Windows Service",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
configDir = filepath.Clean(configDir) configDir = utils.CleanDirInput(configDir)
if !filepath.IsAbs(logFilePath) && utils.IsFileInputValid(logFilePath) { if !filepath.IsAbs(logFilePath) && utils.IsFileInputValid(logFilePath) {
logFilePath = filepath.Join(configDir, logFilePath) logFilePath = filepath.Join(configDir, logFilePath)
} }

View File

@@ -2,7 +2,7 @@
; You need to change the paths for the source files to match your environment ; You need to change the paths for the source files to match your environment
#define MyAppName "SFTPGo" #define MyAppName "SFTPGo"
#define MyAppVersion "0.9.5-dev" #define MyAppVersion "0.9.5.1"
#define MyAppURL "https://github.com/drakkan/sftpgo" #define MyAppURL "https://github.com/drakkan/sftpgo"
#define MyAppExeName "sftpgo.exe" #define MyAppExeName "sftpgo.exe"
#define MyAppDir "C:\Users\vbox\Desktop\sftpgo_setup" #define MyAppDir "C:\Users\vbox\Desktop\sftpgo_setup"
@@ -63,7 +63,7 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
[Run] [Run]
Filename: "netsh"; Parameters: "advfirewall firewall delete rule name=""SFTPGo Service"""; Flags: runhidden Filename: "netsh"; Parameters: "advfirewall firewall delete rule name=""SFTPGo Service"""; Flags: runhidden
Filename: "netsh"; Parameters: "advfirewall firewall add rule name=""SFTPGo Service"" dir=in action=allow program=""{app}\{#MyAppExeName}"""; Flags: runhidden Filename: "netsh"; Parameters: "advfirewall firewall add rule name=""SFTPGo Service"" dir=in action=allow program=""{app}\{#MyAppExeName}"""; Flags: runhidden
Filename: "{app}\{#MyAppExeName}"; Parameters: "service install -c ""{commonappdata}\{#MyAppName}"" -l ""{commonappdata}\{#MyAppName}\logs\sftpgo.log"""; Description: "Install SFTPGo Windows Service"; Flags: runhidden Filename: "{app}\{#MyAppExeName}"; Parameters: "service install -c ""{commonappdata}\{#MyAppName}"" -l ""logs\sftpgo.log"""; Description: "Install SFTPGo Windows Service"; Flags: runhidden
Filename: "{app}\{#MyAppExeName}"; Parameters: "service start"; Description: "Start SFTPGo Windows Service"; Flags: runhidden Filename: "{app}\{#MyAppExeName}"; Parameters: "service start"; Description: "Start SFTPGo Windows Service"; Flags: runhidden
[UninstallRun] [UninstallRun]

View File

@@ -20,6 +20,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"time" "time"
@@ -299,3 +300,19 @@ func IsFileInputValid(fileInput string) bool {
} }
return true return true
} }
// CleanDirInput sanitizes user input for directories.
// On Windows it removes any trailing `"`.
// We try to help windows users that set an invalid path such as "C:\ProgramData\SFTPGO\".
// This will only help if the invalid path is the last argument, for example in this command:
// sftpgo.exe serve -c "C:\ProgramData\SFTPGO\" -l "sftpgo.log"
// the -l flag will be ignored and the -c flag will get the value `C:\ProgramData\SFTPGO" -l sftpgo.log`
// since the backslash after SFTPGO escape the double quote. This is definitely a bad user input
func CleanDirInput(dirInput string) string {
if runtime.GOOS == "windows" {
for strings.HasSuffix(dirInput, "\"") {
dirInput = strings.TrimSuffix(dirInput, "\"")
}
}
return filepath.Clean(dirInput)
}