sftpd: return sftp.ErrSSHFxNoSuchFile if the client ask the file for a missing path

some clients expected this error and not the generic one if the path is missing
This commit is contained in:
Nicola Murino 2019-11-14 14:18:43 +01:00
parent acdf351047
commit 08e85f6be9
4 changed files with 66 additions and 3 deletions

View file

@ -314,7 +314,7 @@ Usage:
sftpgo portable [flags]
Flags:
-C, --advertise-credentials If the service is advertised via multicast DNS this flag allows to put username/password inside the advertised TXT record
-C, --advertise-credentials If the SFTP service is advertised via multicast DNS this flag allows to put username/password inside the advertised TXT record
-S, --advertise-service Advertise SFTP service using multicast DNS (default true)
-d, --directory string Path to the directory to serve. This can be an absolute path or a path relative to the current directory (default ".")
-h, --help help for portable

View file

@ -74,6 +74,6 @@ func init() {
portableCmd.Flags().BoolVarP(&portableAdvertiseService, "advertise-service", "S", true,
"Advertise SFTP service using multicast DNS")
portableCmd.Flags().BoolVarP(&portableAdvertiseCredentials, "advertise-credentials", "C", false,
"If the 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")
rootCmd.AddCommand(portableCmd)
}

View file

@ -220,7 +220,9 @@ func (c Connection) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
c.Log(logger.LevelDebug, logSender, "requested list file for dir: %#v", p)
files, err := ioutil.ReadDir(p)
if err != nil {
if os.IsNotExist(err) {
return nil, sftp.ErrSSHFxNoSuchFile
} else if err != nil {
c.Log(logger.LevelError, logSender, "error listing directory: %#v", err)
return nil, sftp.ErrSSHFxFailure
}

View file

@ -1227,6 +1227,67 @@ func TestMissingFile(t *testing.T) {
os.RemoveAll(user.GetHomeDir())
}
func TestOpenError(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("this test is not available on Windows")
}
usePubKey := false
u := getTestUser(usePubKey)
user, _, err := httpd.AddUser(u, http.StatusOK)
if err != nil {
t.Errorf("unable to add user: %v", err)
}
os.RemoveAll(user.GetHomeDir())
client, err := getSftpClient(user, usePubKey)
if err != nil {
t.Errorf("unable to create sftp client: %v", err)
} else {
defer client.Close()
os.Chmod(user.GetHomeDir(), 0001)
_, err = client.ReadDir(".")
if err == nil {
t.Errorf("read dir must fail if we have no filesystem read permissions")
}
os.Chmod(user.GetHomeDir(), 0755)
testFileSize := int64(65535)
testFileName := "test_file.dat"
testFilePath := filepath.Join(user.GetHomeDir(), testFileName)
err = createTestFile(testFilePath, testFileSize)
if err != nil {
t.Errorf("unable to create test file: %v", err)
}
_, err = client.Stat(testFileName)
if err != nil {
t.Errorf("file stat error: %v", err)
}
localDownloadPath := filepath.Join(homeBasePath, "test_download.dat")
err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
if err != nil {
t.Errorf("file download error: %v", err)
}
os.Chmod(testFilePath, 0001)
err = sftpDownloadFile(testFileName, localDownloadPath, testFileSize, client)
if err == nil {
t.Errorf("file download must fail if we have no filesystem read permissions")
}
err = sftpUploadFile(localDownloadPath, testFileName, testFileSize, client)
if err == nil {
t.Errorf("upload must fail if we have no filesystem write permissions")
}
os.Chmod(user.GetHomeDir(), 0000)
_, err = client.Lstat(testFileName)
if err == nil {
t.Errorf("file stat must fail if we have no filesystem read permissions")
}
os.Chmod(user.GetHomeDir(), 0755)
}
_, err = httpd.RemoveUser(user, http.StatusOK)
if err != nil {
t.Errorf("unable to remove user: %v", err)
}
os.RemoveAll(user.GetHomeDir())
}
func TestOverwriteDirWithFile(t *testing.T) {
usePubKey := false
u := getTestUser(usePubKey)