mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-07 23:00:55 +03:00
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:
@@ -314,7 +314,7 @@ Usage:
|
|||||||
sftpgo portable [flags]
|
sftpgo portable [flags]
|
||||||
|
|
||||||
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)
|
-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 ".")
|
-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
|
-h, --help help for portable
|
||||||
|
|||||||
@@ -74,6 +74,6 @@ 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 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)
|
rootCmd.AddCommand(portableCmd)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
c.Log(logger.LevelDebug, logSender, "requested list file for dir: %#v", p)
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(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)
|
c.Log(logger.LevelError, logSender, "error listing directory: %#v", err)
|
||||||
return nil, sftp.ErrSSHFxFailure
|
return nil, sftp.ErrSSHFxFailure
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1227,6 +1227,67 @@ func TestMissingFile(t *testing.T) {
|
|||||||
os.RemoveAll(user.GetHomeDir())
|
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) {
|
func TestOverwriteDirWithFile(t *testing.T) {
|
||||||
usePubKey := false
|
usePubKey := false
|
||||||
u := getTestUser(usePubKey)
|
u := getTestUser(usePubKey)
|
||||||
|
|||||||
Reference in New Issue
Block a user